zoukankan      html  css  js  c++  java
  • Luogu 3008 [USACO11JAN]道路和飞机Roads and Planes

    BZOJ2200

    听说加上slf优化的spfa的卡过,真的不想写这些东西。

    考虑使用堆优化的dij算法。

    先加上所有双向边,然后dfs一下搜出所有由双向边构成的联通块,然后加上所有的单向边,一边对所有联通块拓扑排序一边在联通块内部处理最短路,因为所有的双向边都是不带负权的,而单向边都是有负权的,所以这样规避dij贪心的错误之处。

    注意到一个$inf$可能被另一个$inf$加上一个负权边拓展得到,所以最后的答案可能会小于$inf$,检验的时候注意取的极大值要小于一开始赋的$inf$。

    时间复杂度$O(nlogn)$。

    Code:

    #include <cstdio>
    #include <cstring>
    #include <queue>
    #include <iostream>
    #include <vector>
    using namespace std;
    typedef pair <int, int> pin;
    
    const int N = 25005;
    const int M = 2e5 + 5;
    const int inf = 1e8;
    
    int n, m1, m2, st, tot = 0, head[N], dis[N];
    int l = 1, r = 0, q[N], deg[N], sccCnt = 0, bel[N];
    bool vis[N];
    vector <int> scc[N];
    
    struct Edge {
        int to, nxt, val;
    } e[M];
    
    inline void add(int from, int to, int val) {
        e[++tot].to = to;
        e[tot].val = val;
        e[tot].nxt = head[from];
        head[from] = tot;
    }
    
    template <typename T>
    inline void read(T &X) {
        X = 0; char ch = 0; T op = 1;
        for(; ch > '9'|| ch < '0'; ch = getchar())
            if(ch == '-') op = -1;
        for(; ch >= '0' && ch <= '9'; ch = getchar())
            X = (X << 3) + (X << 1) + ch - 48;
        X *= op;
    }
    
    void dfs(int x) {
        bel[x] = sccCnt, scc[sccCnt].push_back(x);
        for(int i = head[x]; i; i = e[i].nxt) {
            int y = e[i].to;
            if(!bel[y]) dfs(y);
        }
    }
    
    priority_queue <pin> Q;
    void dij(int c) {
        for(unsigned int i = 0; i < scc[c].size(); i++) Q.push(pin(-dis[scc[c][i]], scc[c][i]));
        for(; !Q.empty(); ) {
            int x = Q.top().second; Q.pop();
            if(vis[x]) continue;
            vis[x] = 1;
            for(int i = head[x]; i; i = e[i].nxt) {
                int y = e[i].to;
                if(bel[y] == c) {
                    if(dis[y] > dis[x] + e[i].val) {
                        dis[y] = dis[x] + e[i].val;
                        Q.push(pin(-dis[y], y));
                    }
                } else {
                    if(dis[y] > dis[x] + e[i].val) dis[y] = dis[x] + e[i].val;
                    deg[bel[y]]--;
                    if(!deg[bel[y]]) q[++r] = bel[y];    
                }
            }
        }
    }
    
    int main() {
        read(n), read(m1), read(m2), read(st);
        for(int x, y, v, i = 1; i <= m1; i++) {
            read(x), read(y), read(v);
            add(x, y, v), add(y, x, v);
        }
        
        for(int i = 1; i <= n; i++)
            if(!bel[i]) ++sccCnt, dfs(i);
        
        for(int x, y, v, i = 1; i <= m2; i++) {
            read(x), read(y), read(v);
            add(x, y, v);
            deg[bel[y]]++;
        }
        
        for(int i = 1; i <= sccCnt; i++)
            if(!deg[i]) q[++r] = i;
        
        memset(dis, 0x3f, sizeof(dis)); dis[st] = 0;
        for(; l <= r; ++l) dij(q[l]);
        
        for(int i = 1; i <= n; i++) {
            if(dis[i] > inf) puts("NO PATH");
            else printf("%d
    ", dis[i]);
        }
            
        return 0;
    }
    View Code
  • 相关阅读:
    再次写给我们这些浮躁的程序员
    SecureCRT的安装与破解,详细过程
    【SecureCRT】SecureCRT 护眼配色
    [Shell]常用语法
    [mysql]查看mysql执行情况的几种方法
    [vbs]脚本启动
    js 获取 网页屏幕高度 窗口高度 元素高度 滚动高度
    angular2 ng build --prod 报错:Module not found: Error: Can't resolve './$$_gendir/app/app.module.ngfactory'
    npm install warning: no description; no repository field
    vscode: Visual Studio Code 常用快捷键
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9562972.html
Copyright © 2011-2022 走看看