codeforces Gym 100338C Important Roads (重建最短路图)

正反两次最短路用于判断边是不是最短路上的边,把最短路径上的边取出来建图。然后求割边。注意重边,和卡spfa。

正权,好好的dijkstra不用,用什么spfa?

#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);
    if(~G3.nxt[G3.head[s]]){
        for(int i = G3.head[s]; ~i; i = G3.nxt[i]){
            cut[id[i]] = 0;
        }
    }
    for(int i = 0; i < m; i ++){
        if(cut[i]) ans.push_back(i+1);
    }
    int sz = ans.size();
    printf("%d
",sz--);
    for(int i = 0; i <= sz; i++){
        printf("%d%c",ans[i],i == sz?'
':' ');
    }
    return 0;
}
原文地址:https://www.cnblogs.com/jerryRey/p/4748495.html