Codeforces Round #Pi (Div. 2) 567E President and Roads ( dfs and similar, graphs, hashing, shortest paths )

图给得很良心,一个s到t的有向图,权值至少为1,求出最短路,如果是一定经过的边,输出"YES",如果可以通过修改权值,保证一定经过这条边,输出"CAN",并且输出最小修改值,否则输出"NO"。保证有s到t的路径,可能有重边。

建正反两个图,分别求出s和t的最短路径,用来判断一条边是不是在最短路径上,然后把最短路径取出来建一个图求割边。

不要用spfa,最坏O(VE),(出卡spfa数据的方法:Hard Test),会TLE 109(数据好啊),自以为是的加了个优化结果跑得更慢了,估计也是那组数据卡的吧,带重边的tarjan处理:前向星i^1!=fa,或者每条边再记录一个信息,不能用v!=fa来判断。。

#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 = 1e5+5;
const int maxe = maxn<<1;
struct Graph
{
    ll d[maxn];
    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,G2,G3;
int id[maxe];

const ll INF = 0x3f3f3f3f3f3f3f3fLL;

int flag[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]) {
                flag[id[i]] = 2;
            }
        }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)
{
    priority_queue<Node> q;
    memset(g.d,0x3f,sizeof(g.d));
    g.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(g.d[v]> g.d[u]+g.w[i]){
                g.d[v] = g.d[u]+g.w[i];
                q.push(Node{g.d[v],v});
            }
        }
    }
    memset(vis,0,sizeof(vis));
}



#define local
int main()
{
#ifdef local
    freopen("in.txt","r",stdin);
   // freopen("out.txt","w",stdout);
#endif // local
    int n,m,s,t;
    scanf("%d%d%d%d",&n,&m,&s,&t);
    for(int i = 0; i < m; i++){
        int u,v,l; scanf("%d%d%d",&u,&v,&l);
        G1.addEdge(u,v,l); G2.addEdge(v,u,l);
    }
    Dijkstra(s,G1);
    Dijkstra(t,G2);
    ll shortest = G1.d[t];
    for(int i = 0; i < m; i++){
        int u = G1.fro[i], v = G1.to[i];
        if(shortest == G1.w[i] + G1.d[u] + G2.d[v] ){
            id[G3.ecnt] = i; G3.addEdge(u,v,G1.w[i]);
            id[G3.ecnt] = i; G3.addEdge(v,u,G1.w[i]);
            flag[i] = 1;
        }
    }
    Tarjan(s,-1);

    for(int i = 0; i < m; i ++){
        if(flag[i] == 2) puts("YES");
        else if(flag[i] == 1){
            if(G1.w[i]>1) printf("CAN 1
");
            else puts("NO");
        }else {
            ll detal = G1.w[i] - shortest + G1.d[G1.fro[i]]+G2.d[G1.to[i]] + 1;
            if(G1.w[i] > detal)
                printf("CAN %d
",detal);
            else puts("NO");
        }
    }
    return 0;
}

/*
自以为是的优化:
    q.push(s);
    while(q.size()){
        int u = q.front(); q.pop();
        for(int i = G1.head[u]; ~i; i = G1.nxt[i]) if(!vis[i]) {
            vis[i] = true;
            int v = G1.to[i];
            if(G1.d[u] + G1.w[i] ==  G1.d[v] && G2.d[v] + G1.w[i] == G2.d[u]){
                id[G3.ecnt] = i; G3.addEdge(u,v,G1.w[i]);
                id[G3.ecnt] = i; G3.addEdge(v,u,G1.w[i]);
                flag[i] = 1;
                q.push(v);
            }
        }
    }
*/
原文地址:https://www.cnblogs.com/jerryRey/p/4712346.html