/*
考虑到测试数据中需要求解任意两点间的最短路,所以采用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 :
", 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("
");
79 printf("Total cost : %d
", 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 }