zoukankan      html  css  js  c++  java
  • bzoj2725

    * 给出一张图
    * 每次删掉一条边后求 the shortest path from S to T
    * 线段树维护最短路径树
    * 具体维护从某点开始偏离最短路而到达 T 的最小距离
    * 首先记录下最短路径
    * 考虑每一种走法都是 S -> a -> x -> y -> b -> T, 其中 S -> a, b -> T 是最短路上的边
    * 把树上的点i能以最短路到达的点标记上Id[i],每个点只标记第一次
    * 枚举所有的边
    * 对于边(u,v),若u从起点标记到的Id[] < v从终点标记到的 Id[]
    * 则线段树区间修改最小值
    * 对于每次用意义的询问,只需输出较小Id[]的点所取到的最小值

    #include <bits/stdc++.h>
     
    const int N = 2e5 + 10;// oo = 999999999;
     
    #define LL long long
     
    const LL oo = 9e18;
     
    int n, m, S, T;
    int Short_path[N], Snum[N], Tnum[N], Id[N], path_js;
    bool vis[N];
    int head[N], now;
    struct Node {int u, v, w, nxt;} G[N << 1];
    LL dis_s[N], dis_t[N];
    LL Minn[N << 2], Ans[N];
     
    inline void Add(int u, int v, int w) {
        G[++ now].v = v, G[now].w = w, G[now].nxt = head[u], head[u] = now;
    }
     
    struct Node_ {
        int u; LL dis;
        bool operator < (const Node_ a) const {
            return dis > a.dis;
        }
    };
     
    std:: priority_queue <Node_> Q;
     
    void Dijkstra(int start, LL dis_[]) {
        for(int i = 1; i <= n; i ++) dis_[i] = oo, vis[i] = 0;
        Node_ now; now = (Node_) {start, 0}; dis_[start] = 0;
        Q.push(now);
        while(!Q.empty()) {
            Node_ topp = Q.top();
            Q.pop();
            if(vis[topp.u]) continue;
            vis[topp.u] = 1;
            for(int i = head[topp.u]; ~ i; i = G[i].nxt) {
                int v = G[i].v;
                if(dis_[v] > dis_[topp.u] + G[i].w) {
                    dis_[v] = dis_[topp.u] + G[i].w;
                    Q.push((Node_) {v, dis_[v]});
                }
            }
        }
    }
     
    inline void Bfs(int x, LL dis_[], int bel[]) {
        std:: queue <int> Q1;
        Q1.push(Short_path[x]);
        bel[Short_path[x]] = x;
        while(!Q1.empty()) {
            int topp = Q1.front();
            Q1.pop();
            for(int i = head[topp]; ~ i; i = G[i].nxt) {
                int v = G[i].v;
                if(!Id[v] && !bel[v] && dis_[v] == dis_[topp] + G[i].w) {
                    bel[v] = x;
                    Q1.push(v);
                }
            }
        }
    }
     
    #define lson jd << 1
    #define rson jd << 1 | 1
     
    void Sec_G(int l ,int r, int jd, int x, int y, LL num) {
        if(x <= l && r <= y) {
            Minn[jd] = std:: min(Minn[jd], (LL)num);
            return ;
        }
        int mid = (l + r) >> 1;
        if(x <= mid) Sec_G(l, mid, lson, x, y, num);
        if(y > mid)  Sec_G(mid + 1, r, rson, x, y, num);
    }
     
    void Dfs_tree(int l, int r, int jd) {
        if(l == r) {
            Ans[l] = Minn[jd];
            return ;
        }
        int mid = (l + r) >> 1;
        Minn[lson] = std:: min(Minn[lson], Minn[jd]);
        Minn[rson] = std:: min(Minn[rson], Minn[jd]);
        Dfs_tree(l, mid, lson), Dfs_tree(mid + 1, r, rson);
    }
     
    #define gc getchar()
     
    inline LL read() {
        LL x = 0; char c = gc;
        while(c < '0' || c > '9') c = gc;
        while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc;
        return x;
    }
     
     main() {
        n = read(), m = read();
        for(int i = 1; i <= (N << 2); i ++) Minn[i] = oo;
        for(int i = 1; i <= n; i ++) head[i] = -1;
        for(int i = 1; i <= m; i ++) {
            int u = read(), v = read(), w = read();
            Add(u, v, w), Add(v, u, w);
        }
        S = read(), T = read();
        if(S == T) {
            int Q = read();
            for(; Q; Q --) puts("0");
            return 0;
        }
        Dijkstra(S, dis_s);
        Dijkstra(T, dis_t);
        if(dis_s[T] == oo) {
            int Q = read();
            for(; Q; Q --) puts("Infinity");
            return 0;
        }
        for(int i = S; i != T; i = i) {
            Short_path[++ path_js] = i;
            Id[i] = path_js;
            for(int j = head[i]; ~ j; j = G[j].nxt) {
                if(dis_t[i] == G[j].w + dis_t[G[j].v]) {
                    i = G[j].v; break;
                }
            }
        }
        Short_path[path_js + 1] = T, Id[T] = path_js + 1;
        for(int i = 1; i <= path_js; i ++) Bfs(i, dis_s, Snum);
        for(int i = path_js + 1; i >= 1; i --) Bfs(i, dis_t, Tnum);
        for(int i = 1; i <= n; i ++) {
            for(int j = head[i]; ~ j; j = G[j].nxt) {
                int v = G[j].v;
                if(Id[i] && Id[v] && abs(Id[i] - Id[v]) == 1) continue;
                if(Snum[i] < Tnum[v] && Snum[i] && Tnum[v]) {
                    Sec_G(1, path_js, 1, Snum[i], Tnum[v] - 1, dis_s[i] + G[j].w + dis_t[v]);
                }               
            }
        }
        Dfs_tree(1, path_js, 1);
        int Q = read();
        for(; Q; Q --) {
            int x = read(), y = read();
            if(Id[x] > Id[y]) std:: swap(x, y);
            if(Id[x] && Id[y] && Id[y] - Id[x] == 1) {
                if(Ans[Id[x]] == oo) puts("Infinity");
                else printf("%lld
    ", Ans[Id[x]]);
            } else printf("%lld
    ", dis_s[T]);
        }
        return 0;
    }
  • 相关阅读:
    Auto-Test 要点纪录(一)
    终端应用变身文件 MD5/SHA1 校验工具
    MD5 algorithm in Objective C
    iphone开发-SQLite数据库使用
    【React】354- 一文吃透 React 事件机制原理
    【Web技术】353- CDN 科普
    【CSS】352- 有趣的CSS弹跳动画
    【Vuejs】351- 带你解析vue2.0的diff算法
    【每周小回顾】7- 一起回顾上周精彩内容
    【Vuejs】350- 学习 Vue 源码的必要知识储备
  • 原文地址:https://www.cnblogs.com/shandongs1/p/9439437.html
Copyright © 2011-2022 走看看