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\n", Ans[Id[x]]);
        } else printf("%lld\n", dis_s[T]);
    }
    return 0;
}

 

posted @ 2018-08-07 21:02  xayata  阅读(223)  评论(0编辑  收藏  举报