【题意】:给出一个无向图,Harry Potter的目的是从1走到n,而Voldemort为了阻止他,使用魔法毁掉了图中的一条边,问最坏情况下Harry要走的最短路是多少。
【题解】:先考虑这么一个问题,如果不允许毁掉图中的边,那么求一次最短路即可。回到初始问题,这是一个最小值最大化的问题,显然最坏情况下肯定是删掉最短路上的一条边,这个很容易理解吧。具体做法:先求一次最短路并记录最短路径,枚举删掉最短路上的每一条边,再求最短路,这些结果中最大值就是最后答案;如果某次删边使得1无法到达n,那么可以跳出枚举,因为这已经是最坏的情况。
【代码】:
1 #include "iostream"
2 #include "cstdio"
3 #include "cstring"
4 #include "queue"
5 using namespace std;
6 #define maxn 1005
7 #define maxm 100500
8 const int inf = 1 << 30;
9 int n, m, s, x;
10 int eh[maxn], dist[maxn], pre[maxn], p[maxn], tot;
11 bool visit[maxn], flag;
12 struct Edge {
13 int u, v, w, next;
14 }et[maxm];
15
16 void init() {
17 tot = 0;
18 memset(eh, -1, sizeof(eh));
19 }
20
21 void addedge(int u, int v, int w) {
22 Edge e = {u, v, w, eh[u]};
23 et[tot] = e;
24 eh[u] = tot++;
25 }
26
27 int spfa() {
28 queue<int> que;
29 fill(dist, dist + maxn, inf);
30 memset(visit, false, sizeof(visit));
31 dist[s] = 0, visit[s] = true;
32 que.push(s);
33 while(!que.empty()) {
34 int u = que.front();
35 que.pop();
36 visit[u] = false;
37 for(int i = eh[u]; i != -1; i = et[i].next) {
38 int v = et[i].v, w = et[i].w;
39 if(dist[u] + w < dist[v] && i != x) {
40 dist[v] = dist[u] + w;
41 if(x == -1) pre[v] = i, p[v] = u;
42 if(!visit[v]) {
43 que.push(v);
44 visit[v] = true;
45 }
46 }
47 }
48 }
49 return dist[n];
50 }
51
52 int solve() {
53 x = -1;
54 int ans = spfa();
55 if(ans == inf) return -1;
56 for(int i = n; i != s; i = p[i]) {
57 x = pre[i];
58 ans = max(ans, spfa());
59 if(ans == inf) return -1;
60 }
61 return ans;
62 }
63
64 int main() {
65 int T;
66 scanf("%d", &T);
67 while(T--) {
68 scanf("%d%d", &n, &m);
69 init();
70 s = 1;
71 for(int i = 0; i < m; i++) {
72 int u, v, w;
73 scanf("%d%d%d", &u, &v, &w);
74 addedge(u, v, w);
75 addedge(v, u, w);
76 }
77 int ans = solve();
78 printf("%d\n", ans);
79 }
80 return 0;
81 }