zoukankan      html  css  js  c++  java
  • 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);
                }
            }
        }
    */
  • 相关阅读:
    图片上传-下载-删除等图片管理的若干经验总结3-单一业务场景的完整解决方案
    图片上传-下载-删除等图片管理的若干经验总结2
    HDU 1195 Open the Lock
    HDU 1690 Bus System
    HDU 2647 Reward
    HDU 2680 Choose the best route
    HDU 1596 find the safest road
    POJ 1904 King's Quest
    CDOJ 889 Battle for Silver
    CDOJ 888 Absurdistan Roads
  • 原文地址:https://www.cnblogs.com/jerryRey/p/4712346.html
Copyright © 2011-2022 走看看