/* 考虑到测试数据中需要求解任意两点间的最短路,所以采用Floyd-Warshall算法 dp[i][j] = min(dp[i][k] + dp[k][j] + tax[k], dp[i][j]); 关键在于记录路径,并且要保证:if there are more minimal paths, output the lexically smallest one. 分两种情况讨论: (1)dp[i][j] > dp[i][k] + dp[k][j] + tax[k] 直接更新dp[i][j],保证获得最短路 (2)dp[i][j] == dp[i][k] + dp[k][j] + tax[k] 看i节点的直接后继节点编号哪个更小,哪个小选哪个,保证获得 the lexically smallest one。 为记录路径: path[i][j] := 在节点i到节点j的最短路径上,i的直接后继节点编号。 初始值:path[i][j] = j 用这种办法可以记录路径的原因: 有n个节点,从1->n的最短路径,假设是这样的1->2->3->4->...->n,则2->n的最短路径 必然是2->3->4->...->n,3->n的最短路径必然是3->4->...->n,如果不是这样的,那么 当前1->n的路径必然不是1->n的最短路径,与假设矛盾。 通过循环即可获得1->n的完整最短路径。 */
1 #include <iostream> 2 #include <cstdlib> 3 #include <cstdio> 4 #include <cstddef> 5 #include <iterator> 6 #include <algorithm> 7 #include <string> 8 #include <locale> 9 #include <cmath> 10 #include <vector> 11 #include <cstring> 12 #include <map> 13 #include <utility> 14 #include <queue> 15 #include <stack> 16 #include <set> 17 using namespace std; 18 const int INF = 0x3f3f3f3f; 19 const int MaxN = 205; 20 const int modPrime = 3046721; 21 22 int N; 23 int dp[MaxN][MaxN]; 24 int tax[MaxN]; 25 int path[MaxN][MaxN]; 26 27 28 void Solve() 29 { 30 for (int i = 0; i < N; ++i) 31 { 32 for (int j = 0; j < N; ++j) 33 { 34 path[i][j] = j; 35 } 36 } 37 for (int k = 0; k < N; ++k) 38 { 39 for (int i = 0; i < N; ++i) 40 { 41 for (int j = 0; j < N; ++j) 42 { 43 //dp[i][j] = min(dp[i][k] + dp[k][j] + tax[k], dp[i][j]); 44 if (dp[i][j] > dp[i][k] + dp[k][j] + tax[k]) 45 { 46 dp[i][j] = dp[i][k] + dp[k][j] + tax[k]; 47 path[i][j] = path[i][k]; 48 } 49 else 50 { 51 if (dp[i][j] == dp[i][k] + dp[k][j] + tax[k]) 52 { 53 if (path[i][j] > path[i][k]) 54 { 55 path[i][j] = path[i][k]; 56 } 57 } 58 } 59 } 60 } 61 } 62 63 int src, dsn; 64 while ((~scanf("%d %d", &src, &dsn)) && !(src == -1 && dsn == -1)) 65 { 66 printf("From %d to %d :\n", src, dsn); 67 printf("Path: "); 68 int tmp = src - 1; 69 printf("%d", src); 70 while (tmp != dsn - 1) 71 { 72 printf("-->"); 73 printf("%d", path[tmp][dsn - 1] + 1); 74 tmp = path[tmp][dsn - 1]; 75 } 76 77 78 printf("\n"); 79 printf("Total cost : %d\n\n", dp[src - 1][dsn - 1]); 80 } 81 } 82 83 int main() 84 { 85 #ifdef HOME 86 freopen("in", "r", stdin); 87 //freopen("out", "w", stdout); 88 #endif 89 90 while (~scanf("%d", &N) && N) 91 { 92 for (int i = 0; i < N; ++i) 93 { 94 for (int j = 0; j < N; ++j) 95 { 96 scanf("%d", &dp[i][j]); 97 if (dp[i][j] == -1) 98 { 99 dp[i][j] = INF; 100 } 101 } 102 } 103 for (int i = 0; i < N; ++i) 104 { 105 scanf("%d", &tax[i]); 106 } 107 Solve(); 108 } 109 110 111 #ifdef HOME 112 cerr << "Time elapsed: " << clock() / CLOCKS_PER_SEC << " ms" << endl; 113 _CrtDumpMemoryLeaks(); 114 #endif 115 return 0; 116 }
时间: 2024-11-13 09:26:35