codeforces Gym 100338C Important Roads

正反两次最短路用于判断边是不是最短路上的边,把最短路径上的边取出来。然后求割边。

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
#define fi first
#define se second
#define bug(x) cout<<#x<<‘=‘<<x<<endl;
#define FOR(i,s,e) for(int i = s; i < e; i++)

const int maxn = 2e4+5;
const int maxe = 2e5+10;
ll d1[maxn],d2[maxn];
struct Graph
{
    int head[maxn],fro[maxe],to[maxe],nxt[maxe],ecnt;
    ll w[maxe];
    void init() {     memset(head,-1,sizeof(head)); ecnt = 0; }
    Graph(){ init(); }
    void addEdge(int u,int v,ll l)
    {
        fro[ecnt] = u;
        to[ecnt] = v;
        w[ecnt] = l;
        nxt[ecnt] = head[u];
        head[u] = ecnt++;
    }
}G1,G3;
int id[maxe];

const ll INF = 0x3f3f3f3f3f3f3f3fLL;

int cut[maxe]; // 0 not shortest path 1 shortest path 2 unique shortest path
int dfs_clock,dfn[maxn],low[maxn];
void Tarjan(int u,int fa)
{
    dfn[u] = low[u] = ++dfs_clock;
    for(int i = G3.head[u]; ~i; i = G3.nxt[i]){
        if((i^1) == fa) continue;
        int v = G3.to[i];
        if(!dfn[v]){
            Tarjan(v,i);
            low[u] = min(low[u],low[v]);
            if(low[v]>dfn[u]) {
                cut[id[i]] = 1;
            }
        }else { low[u] = min(low[u],low[v]); }
    }
}
struct Node
{
    ll d;
    int u;
    bool operator < (const Node& x) const{
        return d > x.d;
    }
};

bool vis[maxn];
void Dijkstra(int s,Graph &g,ll (&d)[maxn])
{
    memset(vis,0,sizeof(vis));
    priority_queue<Node> q;
    memset(d,0x3f,sizeof(d));
    d[s] = 0;
    q.push(Node{0,s});
    while(q.size()){
        Node x = q.top(); q.pop();
        int u = x.u;
        if(vis[u]) continue;
        vis[u] = true;
        for(int i = g.head[u]; ~i; i = g.nxt[i] ){
            int v = g.to[i];
            if(v == u) continue;
            if(d[v]> d[u]+g.w[i]){
                d[v] = d[u]+g.w[i];
                q.push(Node{d[v],v});
            }
        }
    }
}

vector<int> ans;
bool evis[maxe];

int main()
{
    freopen("important.in","r",stdin);
    freopen("important.out","w",stdout);
    int n,m,s,t;
    scanf("%d%d",&n,&m);
    s = 1; t = n;
    for(int i = 0; i < m; i++){
        int u,v,l; scanf("%d%d%d",&u,&v,&l);
        G1.addEdge(u,v,l); G1.addEdge(v,u,l);
    }
    Dijkstra(s,G1,d1);
    Dijkstra(t,G1,d2);
    ll shortest = d1[t];
    for(int i = 0,M = m*2; i < M; i++){
        int u = G1.fro[i], v = G1.to[i];
        if(shortest == G1.w[i] + d1[u] + d2[v] ){
            int eid = i/2;
            if(!evis[eid]){
                evis[eid] = true;
                id[G3.ecnt] = eid; G3.addEdge(u,v,G1.w[i]);
                id[G3.ecnt] = eid; G3.addEdge(v,u,G1.w[i]);
            }
        }
    }
    Tarjan(s,-1);

    for(int i = 0; i < m; i ++){
        if(cut[i]) ans.push_back(i+1);
    }
    int sz = ans.size();
    printf("%d\n",sz);
    for(int i = 0; i < sz; i++){
        printf("%d%c",ans[i],i == sz?‘\n‘:‘ ‘);
    }
    return 0;
}
时间: 2024-08-07 12:39:51

codeforces Gym 100338C Important Roads的相关文章

Gym - 100338C Important Roads 最短路+tarjan

题意:给你一幅图,问有多少条路径使得去掉该条路后最短路发生变化. 思路:先起始两点求两遍单源最短路,利用s[u] + t[v] + G[u][v] = dis 找出所有最短路径,构造新图.在新图中找到所有的桥输出就可以了. 1 #include <iostream> 2 #include <cstdio> 3 #include <fstream> 4 #include <algorithm> 5 #include <cmath> 6 #inclu

Codeforces gym Hello 2015 Div1 B and Div2 D

Codeforces gym 100571 problem D Problem 给一个有向图G<V,E>和源点S,边的属性有长度L和颜色C,即E=<L,C>.进行Q次询问,每次给定一个点X,输出S到X的最短路的长度(不存在则输出 -1).但要求S到X的路径中相邻两条边颜色不一样. Limits Time Limit(ms): 1000 Memory Limit(MB): 256 |V|, |E|: [1, 10^5] X, S: [1, |V| ] L: [1, 10^9] |C|

ACdream 1415 Important Roads

Important Roads Special JudgeTime Limit: 20000/10000MS (Java/Others)Memory Limit: 128000/64000KB (Java/Others) Problem Description The city where Georgie lives has n junctions some of which are connected by bidirectional roads.      Every day Georgie

Codeforces gym Hello 2015 Div1 E

Codeforces gym 100570 problem E (一种处理动态最长回文子串问题的方法) Problem 给一个长度为N的字符串S,字符集是'a'-'z'.进行Q次操作,操作分三种.一,修改位置X的字符为C:二,查询以P位置为中心的最长回文子串的长度,并输出:三,查询以P与P+1的中间位置为中心的最长回文子串的长度,并输出. More 第二种操作子串长度为奇数,一定存在:第三种操作子串长度为偶数,若不存在,输出 -1. Limits Time Limit(ms): 4000(1s足

Codeforces 191C Fools and Roads(树链剖分)

题目链接:Codeforces 191C Fools and Roads 题目大意:给定一个N节点的数,然后有M次操作,每次从u移动到v,问说每条边被移动过的次数. 解题思路:树链剖分维护边,用一个数组标记即可,不需要用线段树. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int maxn = 1e5 + 5; int N, Q, ne, fir

Codeforces gym Hello 2015 Div1 C and Div2 E

Codeforces gym 100570 problem C Codeforces gym 100571 problem E Problem 给一个N行M列的矩阵Ma,进行Q次(Q<=10)查询,每次给定一个K,问有多少子矩阵,满足最大值max - 最小值min <=K. Limits Time Limit(ms): 8000 Memory Limit(MB): 512 N, M: [1, 400] Q: [1, 10] Ma(i, j), K: [1, 10^9] Solution (Th

【模拟】ECNA 2015 I What&#39;s on the Grille? (Codeforces GYM 100825)

题目链接: http://codeforces.com/gym/100825 题目大意: 栅栏密码.给定N(N<=10),密钥为一个N*N的矩阵,'.'代表空格可以看到,'X'代表被遮挡,还有密文字符串S,长度为N*N 每次将这个矩阵顺时针旋转90°,把矩阵中空格对应的位置按照从上到下从左到右的顺序依次填充上密文字符,求最终这个密文字符能否填满N*N的矩阵,能按顺序输出得到的答案,不能输出"invalid grille" 题目思路: [模拟] 直接模拟即可.旋转的坐标公式很好推.

CodeForces 567E President and Roads(最短路 + tarjan)

CodeForces 567E President and Roads Description Berland has n cities, the capital is located in city s, and the historic home town of the President is in city t (s?≠?t). The cities are connected by one-way roads, the travel time for each of the road

Codeforces gym Hello 2015 Div2 B

Codeforces gym 100571 problem B Problem 设函数F(x),F(1)与F(2)已知,且当 i>=3,F(i)=a*F(i-2)+b*F(i-1).再给一个长度为N的数列A,进行Q次如下操作:每次给一个区间[L, R],对于每个k(L=<k<=R),将A[k]=A[k]+F[k-L+1].最后输出数列A(mod 10^9+7). Limits Time Limit(ms): 1000 Memory Limit(MB): 256 N, Q: [1, 10^