//除了边的权值之外每个点还附带一个权值,所以在松弛操作的时候要把点的权值也计算进去
//另外在总费用最小的情况下要输出字典序最小的路径,同样是在松弛操作那里处理
//如果能更新d[i]使d[i]变小则直接更新
//另外在总费用最小的情况下要输出字典序最小的路径,同样是在松弛操作那里处理
//如果能更新d[i]使d[i]变小则直接更新
//如果是与d[i]相同则判断一下如果更新的话会不会使路径的字典序更小,如果能才更新否则不更新;这一点和记录花费那很像
#include <iostream> #include <memory.h> #include <stdio.h> using namespace std; #define Max_V 1005 const int IN = (1<<28); int G[105][105]; int Path[105][105]; int Tax[105]; int N,S,D; void Floyd() { for( int u = 1; u <= N; u++ ) for( int v = 1; v <= N; v++ ) for( int w = 1; w <= N; w++ ) { if( G[v][w] > G[v][u] + G[u][w] + Tax[u] ) { G[v][w] = G[v][u] + G[u][w]+ Tax[u]; Path[v][w] = Path[v][u]; } else if( G[v][w] == G[v][u] + G[u][w] + Tax[u] ) { if( Path[v][w] > Path[v][u] ) { Path[v][w] = Path[v][u]; } } } } void Print(int i, int j) { if( i==j ) { printf("%d",i); return; } printf("%d-->",i); Print(Path[i][j],j); } int main() { while( cin >> N, N!=0) { memset(G, 0, sizeof(G)); memset(Path, 0, sizeof(Path)); for( int i = 1; i <= N; i++ ) { for( int j = 1; j <= N; j++ ) { Path[i][j] = j; cin >> G[i][j]; if( G[i][j] == -1 ) { G[i][j] = IN; } } } for( int i = 1; i <= N; i++ ) cin >> Tax[i]; Floyd(); while( cin >> S >> D, S != -1 || D != -1 ) { if( S==D ) { printf("From %d to %d :\n",S,D); printf("Path: %d\n",S); printf("Total cost : %d\n\n", 0); continue; } printf("From %d to %d :\n",S,D); printf("Path: "); Print(S,D); printf("\n"); printf("Total cost : %d\n\n", G[S][D]); } } return 0; }