题目连接:http://www.wikioi.com/problem/1021/
题目描述 Description
麦克找了个新女朋友,玛丽卡对他非常恼火并伺机报复。
因为她和他们不住在同一个城市,因此她开始准备她的长途旅行。
在这个国家中每两个城市之间最多只有一条路相通,并且我们知道从一个城市到另一个城市路上所需花费的时间。
麦克在车中无意中听到有一条路正在维修,并且那儿正堵车,但没听清楚到底是哪一条路。无论哪一条路正在维修,从玛丽卡所在的城市都能到达麦克所在的城市。
玛丽卡将只从不堵车的路上通过,并且她将按最短路线行车。麦克希望知道在最糟糕的情况下玛丽卡到达他所在的城市需要多长时间,这样他就能保证他的女朋友离开该城市足够远。
编写程序,帮助麦克找出玛丽卡按最短路线通过不堵车道路到达他所在城市所需的最长时间(用分钟表示)。
输入描述 Input Description
第一行有两个用空格隔开的数N和M,分别表示城市的数量以及城市间道路的数量。1≤N≤1000,1≤M≤N*(N-1)/2。城市用数字1至N标识,麦克在城市1中,玛丽卡在城市N中。
接下来的M行中每行包含三个用空格隔开的数A,B和V。其中1≤A,B≤N,1≤V≤1000。这些数字表示在A和城市B中间有一条双行道,并且在V分钟内是就能通过。
输出描述 Output Description
输出文件的第一行中写出用分钟表示的最长时间,在这段时间中,无论哪条路在堵车,玛丽卡应该能够到达麦克处,如果少于这个时间的话,则必定存在一条路,该条路一旦堵车,玛丽卡就不能够赶到麦克处。
样例输入 Sample Input
5 7
1 2 8
1 4 10
2 3 9
2 4 10
2 5 1
3 4 7
3 5 10
样例输出 Sample Output
27
一道最短路径,题目意思是比较好理解: 当有无向图去掉一边后,求这m(边数)种情况中最短路径的最大值。
如果枚举每种情况, 则要进行计算m次最短路径, 势必会超时。 换种想法, 如果s 是未去边时的一条最短路径, 则 当去除s以为的路径,肯定会大于s的最短路径值, 所以只有求出一条最短路径, 然后枚举这条路径上的每条边就可以了。
先放Dijkstra版+邻接矩阵, 由于用了一种非常烂的 求路径方法, 使得代码、速度都和翔一样 又臭又长, 不过可能数据比较水吧,还是过了。
1 #define _CRT_SECURE_NO_WARNINGS 2 #include <iostream> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 #include <queue> 7 #include <cstdio> 8 using namespace std; 9 const int INF = 500000000; 10 const int maxn = 1004; 11 int v[maxn]; 12 int d[maxn]; 13 int w[maxn][maxn]; 14 int n, m; 15 int path[maxn]; 16 17 struct Node { 18 int b; 19 int e; 20 }; 21 22 vector<Node> rssp; 23 queue<Node> qssp; 24 void dijkstra() { 25 memset(v, 0, sizeof(v)); 26 for (int i = 0; i < n; ++i) 27 d[i] = (i == 0 ? 0 : INF); 28 for (int i = 0; i < n; ++i) { 29 int x, m = INF; 30 for (int y = 0; y < n; ++y) if (!v[y] && d[y] <= m) m = d[x = y]; 31 v[x] = 1; 32 for (int y = 0; y < n; ++y) { 33 if (d[y] > d[x] + w[x][y]) { 34 d[y] = d[x] + w[x][y]; 35 } 36 } 37 } 38 } 39 40 void findssp() { 41 int i = 0, tempb; 42 Node temp; 43 for (i = 0; i < n; ++i) 44 if (w[n - 1][i] != INF && d[n - 1] - d[i] == w[n - 1][i]) { 45 temp.b = n - 1; 46 temp.e = i; 47 rssp.push_back(temp); 48 qssp.push(temp); 49 break; 50 } 51 while (!qssp.empty()) { 52 tempb = qssp.front().e; 53 qssp.pop(); 54 for (i = 0; i < n; ++i) 55 if (w[tempb][i] != INF && d[tempb] - d[i] == w[tempb][i]) { 56 temp.b = tempb; 57 temp.e = i; 58 rssp.push_back(temp); 59 qssp.push(temp); 60 break; 61 } 62 } 63 } 64 65 int main() { 66 67 int i, j, x, y, val, maxpath; 68 Node tempnode; 69 scanf("%d%d", &n, &m); 70 for (i = 0; i < n; ++i) 71 for (j = 0; j < n; ++j) 72 w[i][j] = INF; 73 for (i = 0; i < m; ++i) { 74 scanf("%d%d%d", &x, &y, &val); 75 w[x - 1][y - 1] = w[y - 1][x - 1] = val; 76 } 77 dijkstra(); 78 findssp(); 79 maxpath = d[n - 1]; 80 while (!rssp.empty()) { 81 tempnode = rssp.back(); 82 rssp.pop_back(); 83 val = w[tempnode.b][tempnode.e]; 84 w[tempnode.b][tempnode.e] = INF; 85 w[tempnode.e][tempnode.b] = INF; 86 dijkstra(); 87 if (d[n - 1] > maxpath) maxpath = d[n - 1]; 88 w[tempnode.b][tempnode.e] = w[tempnode.e][tempnode.b] = val; 89 } 90 cout << maxpath << endl; 91 92 return 0; 93 }
接下来是spfa+邻接表,根据题目测试数据范围,应该速度差不多才对, 不过不晓得为什么,差很多, 虽然换了种反复, 但求路径的复杂度只有(n) 可能还是与测试数据有关吧?!
1 /***Good Luck***/ 2 #define _CRT_SECURE_NO_WARNINGS 3 #include <iostream> 4 #include <cstdio> 5 #include <cstdlib> 6 #include <cstring> 7 #include <string> 8 #include <algorithm> 9 #include <stack> 10 #include <map> 11 #include <queue> 12 #include <vector> 13 #include <set> 14 #include <functional> 15 #include <cmath> 16 17 #define Min(a,b) (a < b ? a : b) 18 #define Max(a,b) (a > b ? a : b) 19 #define Zero(a) memset(a, 0, sizeof(a)) 20 #define Neg(a) memset(a, -1, sizeof(a)) 21 #define All(a) a.begin(), a.end() 22 #define pb push_back 23 24 using namespace std; 25 typedef long long ll; 26 27 int get_val() { 28 int ret(0); 29 char c; 30 while ((c = getchar()) == ' ' || c == ' ' || c == ' '); 31 ret = c - '0'; 32 while ((c = getchar()) >= '0' && c <= '9') 33 ret += ret * 10 + (c - '0'); 34 return ret; 35 } 36 const int maxv = 1005; 37 const int maxe = 500010; 38 const int INF = 1e8; 39 int n, m, done[maxv], dis[maxv], path[maxv]; 40 struct Node { 41 int to; 42 int val; 43 Node(int t, int v) : to(t), val(v) {} 44 }; 45 vector<Node> v[maxv]; 46 queue<int> buff; 47 48 void spfa(int st, int flag) { 49 Zero(done); 50 while (!buff.empty()) buff.pop(); 51 for (int i = 1; i <= n; ++i) { 52 dis[i] = INF; 53 } 54 dis[st] = 0; 55 buff.push(st); 56 done[st] = 1; 57 int tmpto, tmpval; 58 while (!buff.empty()) { 59 int tmp = buff.front(); 60 for (int i = 0; i < (int)v[tmp].size(); ++i) { 61 tmpto = v[tmp][i].to; 62 tmpval = v[tmp][i].val; 63 if (dis[tmp] + tmpval < dis[tmpto]) { 64 dis[tmpto] = dis[tmp] + tmpval; 65 if (flag) 66 path[tmpto] = tmp; //如果路径更短,则更新指向上一个节点 67 if (!done[tmpto]) { 68 buff.push(tmpto); 69 done[tmpto] = 1; 70 } 71 } 72 } 73 buff.pop(); 74 done[tmp] = 0; 75 } 76 } 77 int main() { 78 int i, j; 79 int bn, ed, w; 80 scanf("%d%d", &n, &m); 81 for (i = 1; i <= m; ++i) { 82 scanf("%d%d%d", &bn, &ed, &w); 83 v[bn].push_back(Node(ed, w)); 84 v[ed].pb(Node(bn, w)); 85 } 86 spfa(1, 1); 87 ed = path[n]; 88 bn = n; 89 int ans = dis[n]; 90 int tmp; 91 while (true) { 92 for (i = 0; i < (int)v[bn].size(); ++i) { 93 if (ed == v[bn][i].to) { 94 tmp = v[bn][i].val; 95 v[bn][i].val = INF; 96 break; 97 } 98 } 99 for (i = 0; i < (int)v[ed].size(); ++i) { 100 if (bn == v[ed][i].to) { 101 v[ed][i].val = INF; 102 break; 103 } 104 } 105 spfa(1, 0); 106 ans = Max(dis[n], ans); 107 for (i = 0; i < (int)v[bn].size(); ++i) { 108 if (ed == v[bn][i].to) { 109 v[bn][i].val = tmp; 110 break; 111 } 112 } 113 for (i = 0; i < (int)v[ed].size(); ++i) { 114 if (bn == v[ed][i].to) { 115 v[ed][i].val = tmp; 116 break; 117 } 118 } 119 if (ed == 1) break; 120 bn = ed; 121 ed = path[bn]; 122 } 123 printf("%d ", ans); 124 return 0; 125 }