题目大意:有N个点,M条路,如果两条路不连通的话,就将这两条路的距离设置为L
现在要求你求出每两点之间的最短距离和
接着要求
求出炸断 给出的M条路中的一条路后,每两点之间的最短距离和的最大值(翻译来自http://blog.csdn.net/l123012013048/article/details/47297393)
单源最短路树:把源点到其他点的最短路拼起来,形成最短路树(可能有多棵,这里只需要一棵)。我们把起点为i的单源最短路树称为i源最短路树。想要让最短路改变,删除的边必定在这课最短路树上(但反过来不成立,即删除最短路树上的边最短路改变,是错误的)。处理出单源最短路树,然后用belong[i][j]表示边i是否在j源最短路树上,枚举边,重新做belong[i][j]为1的点即可。
这里仅仅是带来常数上的优化,实际复杂度并不能改变(nm^2logn),蓝书说复杂度变了(n^2mlogn)。。我不敢苟同
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <queue> 7 #include <vector> 8 #include <map> 9 #include <string> 10 #include <cmath> 11 #define min(a, b) ((a) < (b) ? (a) : (b)) 12 #define max(a, b) ((a) > (b) ? (a) : (b)) 13 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a)) 14 template<class T> 15 inline void swap(T &a, T &b) 16 { 17 T tmp = a;a = b;b = tmp; 18 } 19 inline void read(int &x) 20 { 21 x = 0;char ch = getchar(), c = ch; 22 while(ch < '0' || ch > '9') c = ch, ch = getchar(); 23 while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar(); 24 if(c == '-') x = -x; 25 } 26 const int INF = 0x3f3f3f3f; 27 const int MAXN = 200 + 10; 28 const int MAXM = 2000 + 10; 29 struct Edge 30 { 31 int u,v,w,nxt; 32 Edge(int _u, int _v, int _w, int _nxt){u = _u, v = _v, w = _w, nxt = _nxt;} 33 Edge(){} 34 }edge[MAXM << 1]; 35 int head[MAXN], cnt = 1, d[MAXN][MAXN], dis[MAXM], flag, belong[MAXM][MAXN], vis[MAXN], p[MAXN][MAXN], l, tmp1, tmp2, tmp3, n, m; 36 //p[i]表示以i为起点的最短路树,在最短路树上,j的父亲的那条边 37 inline void insert(int a, int b, int c) 38 { 39 edge[++ cnt] = Edge(a,b,c,head[a]), head[a] = cnt; 40 } 41 struct Node 42 { 43 int u,w; 44 Node(int _u, int _w){u = _u, w = _w;} 45 Node(){} 46 }; 47 struct cmp 48 { 49 bool operator()(Node a, Node b) 50 { 51 return a.w > b.w; 52 } 53 }; 54 std::priority_queue<Node, std::vector<Node>, cmp> q; 55 void dij(int S, int *d, int size) 56 { 57 while(q.size())q.pop();memset(d, 0x3f, size), d[S] = 0, memset(vis, 0, sizeof(vis)), q.push(Node(S, 0)); 58 while(q.size()) 59 { 60 Node now = q.top();q.pop(); 61 if(vis[now.u]) continue; vis[now.u] = 1; 62 for(int pos = head[now.u];pos;pos = edge[pos].nxt) 63 { 64 int v = edge[pos].v; 65 if(d[v] > d[now.u] + edge[pos].w) 66 { 67 d[v] = d[now.u] + edge[pos].w, q.push(Node(v, d[v])); 68 if(flag) p[S][v] = pos; 69 } 70 } 71 } 72 } 73 int main() 74 { 75 while(scanf("%d %d %d", &n, &m, &l) != EOF) 76 { 77 flag = 1, memset(head, 0, sizeof(head)), memset(belong, 0, sizeof(belong)), memset(p, 0, sizeof(p)), cnt = 1; 78 for(int i = 1;i <= m;++ i) read(tmp1), read(tmp2), read(tmp3), insert(tmp1, tmp2, tmp3), insert(tmp2, tmp1, tmp3); 79 for(int i = 1;i <= n;++ i) dij(i, d[i], sizeof(d[i])); 80 long long ans1 = 0, ans2 = ans1, ans3 = 0; 81 for(int i = 1;i <= n;++ i) 82 for(int j = 1;j <= n;++ j) 83 if(d[i][j] >= INF) ans1 += l; 84 else ans1 += d[i][j]; 85 printf("%lld ", ans1); 86 flag = ans3 = 0; 87 for(int i = 1;i <= n;++ i) 88 for(int j = 1;j <= n;++ j) 89 if(p[i][j]) belong[p[i][j]][i] = 1; 90 for(int pos = 2;pos <= cnt;pos += 2) 91 { 92 tmp1 = edge[pos].w;ans2 = ans1; 93 edge[pos].w = edge[pos ^ 1].w = INF; 94 for(int S = 1;S <= n;++ S) 95 if(belong[pos][S] || belong[pos^1][S]) 96 { 97 dij(S, dis, sizeof(dis)); 98 for(int i = 1;i <= n;++ i) 99 { 100 if(d[S][i] >= INF) ans2 -= l; 101 else ans2 -= d[S][i]; 102 if(dis[i] >= INF) ans2 += l; 103 else ans2 += dis[i]; 104 } 105 } 106 edge[pos].w = edge[pos ^ 1].w = tmp1; 107 ans3 = max(ans3, ans2); 108 } 109 printf("%lld ", ans3); 110 } 111 return 0; 112 }