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; }