|
|
|
@ -1,71 +0,0 @@
|
|
|
|
|
#include <bits/stdc++.h>
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
|
|
const int N = 110;
|
|
|
|
|
const int INF = 0x3f3f3f3f;
|
|
|
|
|
// Floyd+记录终点前驱
|
|
|
|
|
int n;
|
|
|
|
|
int g[N][N], w[N];
|
|
|
|
|
int path[N][N]; // 记录i到j最短路径中j的前驱
|
|
|
|
|
|
|
|
|
|
void floyd() {
|
|
|
|
|
for (int k = 1; k <= n; k++)
|
|
|
|
|
for (int i = 1; i <= n; i++)
|
|
|
|
|
for (int j = 1; j <= n; j++) {
|
|
|
|
|
if (g[i][j] > g[i][k] + g[k][j] + w[k]) {
|
|
|
|
|
g[i][j] = g[i][k] + g[k][j] + w[k];
|
|
|
|
|
path[i][j] = path[i][k]; // i->j这条最短路径上,i后面第一个节点,是i->k路径上第一个节点
|
|
|
|
|
}
|
|
|
|
|
// 相同路径下选择后继更小的(为了字典序)
|
|
|
|
|
if (g[i][j] == g[i][k] + g[k][j] + w[k])
|
|
|
|
|
if (path[i][j] > path[i][k])
|
|
|
|
|
path[i][j] = path[i][k];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 递归输出路径
|
|
|
|
|
void print(int s, int e) {
|
|
|
|
|
printf("-->%d", path[s][e]); // 输出s的后继
|
|
|
|
|
if (path[s][e] != e) // 如果不是直连
|
|
|
|
|
print(path[s][e], e); // 递归输出后继
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
From 1 to 3 :
|
|
|
|
|
Path: 1-->5-->4-->3
|
|
|
|
|
Total cost : 21
|
|
|
|
|
|
|
|
|
|
From 3 to 5 :
|
|
|
|
|
Path: 3-->4-->5
|
|
|
|
|
Total cost : 16
|
|
|
|
|
|
|
|
|
|
From 2 to 4 :
|
|
|
|
|
Path: 2-->1-->5-->4
|
|
|
|
|
Total cost : 17
|
|
|
|
|
*/
|
|
|
|
|
int main() {
|
|
|
|
|
#ifndef ONLINE_JUDGE
|
|
|
|
|
freopen("HDU1385.in", "r", stdin);
|
|
|
|
|
#endif
|
|
|
|
|
while (cin >> n, n) {
|
|
|
|
|
for (int i = 1; i <= n; i++)
|
|
|
|
|
for (int j = 1; j <= n; j++) {
|
|
|
|
|
cin >> g[i][j];
|
|
|
|
|
if (g[i][j] == -1) g[i][j] = INF;
|
|
|
|
|
path[i][j] = j;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (int i = 1; i <= n; i++) cin >> w[i];
|
|
|
|
|
floyd();
|
|
|
|
|
|
|
|
|
|
int s, e;
|
|
|
|
|
|
|
|
|
|
while (cin >> s >> e, ~s && ~e) {
|
|
|
|
|
printf("From %d to %d :\n", s, e);
|
|
|
|
|
printf("Path: %d", s);
|
|
|
|
|
if (s != e) print(s, e); // 起点与终点不同开始递归
|
|
|
|
|
printf("\nTotal cost : %d\n\n", g[s][e]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|