#include 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最短路径中i的后继 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; }