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);
                }
            }
        }
    */
  • 相关阅读:
    交互原型设计软件axure rp学习之路(一)
    charles关于手机APP抓包
    Charles常见问题汇总
    转: Charles 从入门到精通
    深度理解《正则表达式》
    monkey无规则压力测试
    go语言几个最快最好运用最广的web框架比较
    html 生成印章
    通过URI协议实现浏览器调用手机app
    基于GitLab+Jenkins的DevOps赋能实践
  • 原文地址:https://www.cnblogs.com/jerryRey/p/4712346.html
Copyright © 2011-2022 走看看