zoukankan      html  css  js  c++  java
  • Codeforces Round #Pi (Div. 2) E. President and Roads 最短路+桥

    题目链接:

    http://codeforces.com/contest/567/problem/E

    题意:

    给你一个带重边的图,求三类边:

    在最短路构成的DAG图中,哪些边是必须经过的;

    其他的(包括不在DAG上的边)不是必须经过的边把权值改小多少才能通过,

    或者根本不可能通过的。

    题解:

    从起点s跑一遍最短路得到d[maxn],从终点t跑一遍最短路得到d2[maxn],对于边(u,v,w),如果d[u]+d2[v]+w==d[t]那么这条边在最短路上,对于不在最短路上的边,如果d[u]+d2[v]+w-d[t]+1<w则可以重建,否则输出NO。

    对于所有最短路构成的DAG(建成无向图)跑一遍tarjan求割边,所有的割边输出YES。

    代码:

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    #include<queue>
    using namespace std;
    
    typedef __int64 LL;
    #define INF (1LL<<61)
    
    struct Edge {
        int u, v, type,bri,id;
        LL w;
        Edge(int u, int v, LL w,int id) :u(u), v(v), w(w), type(0),bri(0),id(id) {}
    };
    
    void addEdge(vector<int> G[],vector<Edge> &egs,int u, int v, int w,int id=0) {
        egs.push_back(Edge(u, v, w,id));
        G[u].push_back(egs.size() - 1);
    }
    
    const int maxn = 2e5 + 10;
    const int maxm = maxn * 2;
    int n, m, s, t;
    
    vector<int> G[maxn],G2[maxn];
    vector<Edge> egs,egs2;
    
    struct Heap {
        int v; LL d;
        Heap(int v, LL d) :v(v), d(d) {}
        bool operator < (Heap tmp) const {
            return d > tmp.d;
        }
    };
    
    LL d[maxn], d2[maxn];
    int done[maxn];
    void dijkstral(vector<int> G[], vector<Edge> &egs,LL *d, int s) {
        for (int i = 0; i < maxn; i++) d[i] = INF;
        memset(done, 0, sizeof(done));
        priority_queue<Heap> pq;
        d[s] = 0, pq.push(Heap(s,0));
        while (!pq.empty()) {
            int u = pq.top().v; pq.pop();
            if (done[u]) continue;
            done[u] = 1;
            for (int i = 0; i < G[u].size(); i++) {
                Edge& e = egs[G[u][i]];
                if (d[e.v] > d[u] + e.w) {
                    d[e.v] = d[u] + e.w;
                    pq.push(Heap(e.v, d[e.v]));
                }
            }
        }
    }
    
    vector<int> DAG[maxn];
    vector<Edge> egs3;
    
    int pre[maxn], low[maxn], dfs_clock;
    int dfs(vector<int> G[],vector<Edge> &egs,int u) {
        int lowu = pre[u] = ++dfs_clock;
        int child = 0;
        for (int i = 0; i < G[u].size(); i++) {
            Edge &e = egs[G[u][i]];
            if (e.type == 1) continue;
            egs[G[u][i] ^ 1].type = 1;
            if (!pre[e.v]) {
                child++;
                int lowv = dfs(G, egs, e.v);
                lowu = min(lowu, lowv);
                if (lowv > pre[u]) {
                    e.bri = 1;
                }
            }
            else if (pre[e.v] < pre[u]) {
                lowu = min(lowu, pre[e.v]);
            }
        }
        low[u] = lowu;
        return lowu;
    }
    
    int main() {
        scanf("%d%d%d%d", &n, &m, &s, &t),s--,t--;
        for (int i = 0; i < m; i++) {
            int u, v, w;
            scanf("%d%d%d", &u, &v, &w),u--,v--;
            addEdge(G,egs,u, v, w);
            addEdge(G2, egs2, v, u, w);
        }
        dijkstral(G,egs,d,s);
        dijkstral(G2, egs2,d2, t);
    
        for (int i = 0; i < egs.size(); i++) {
            Edge& e = egs[i];
            if (e.w+d[e.u]+d2[e.v]==d[t]) {
                addEdge(DAG, egs3, e.u, e.v, e.w,i);
                addEdge(DAG, egs3, e.v, e.u, e.w,i);
            }
        }
    
        memset(pre, 0, sizeof(pre));
        dfs_clock = 0;
        dfs(DAG, egs3, s);
        for (int i = 0; i < egs3.size(); i++) {
            Edge& e = egs3[i];
            if (e.bri) {
                egs[e.id].bri = 1;
            }
        }
        for (int i = 0; i < egs.size(); i++) {
            Edge& e = egs[i];
            if (e.bri) printf("YES
    ");
            else {
                LL delta = d[e.u] + d2[e.v] + e.w - d[t] + 1;
                if (delta<e.w) printf("CAN %I64d
    ", delta);
                else printf("NO
    ");
            }
        }
        return 0;
    }

    总结:

    这题跳了两个坑:

    1、距离和会爆int:

    发现问题之后改了d[maxn],但是一直没发现Heap结构体里面的d没有改!!!!wa了七八次!

    2、卡spfa的时间!!!

    。。

    代码调试出错误的时候,改正一定要彻底!不要有的地方改了有的地方漏了!比如dijkstra,改了d还要改Heap结构体!!!

  • 相关阅读:
    测试可以自动化,日常工作也可以自动化,autoit帮你搞定!
    工作了几年的IT人想要创业,必看的失败经验
    使用autoit,可以节省您很多时间
    美容院会籍管理,看着简单,其实很复杂
    简历,求职求项目,硕士4年工作经验2年管理经验
    maven+svn+hudson+weblogic构建持续集成环境
    快速开发框架V0.001(免费、100%开源)
    进销存管理系统的设计与实现
    窗体的位置startposition manual
    破解网页文章无法复制方法全集合
  • 原文地址:https://www.cnblogs.com/fenice/p/5621179.html
Copyright © 2011-2022 走看看