还要字典序啊
#include <iostream>
#include<cstring>
#include<cstdlib>
#include<string>
#include<cstdio>
#include<queue>
#include<stack>
#include<list>
#include<set>
#include<map>
#define INF 99999999
using namespace std;
int Edge[100][100];
int cost[100];
int path[100][100];
int main()
{
int i,j,k,n,m,u,v,len,s,g,w,str,end;
while(cin>>n&&n)
{
for(i=1; i<=n; i++)
for(j=1; j<=n; j++)
{
scanf("%d",&w);
if(w==-1)
Edge[i][j]=INF;
else
Edge[i][j]=w;
path[i][j]=j; //i到j这条路 i的后继结点为j 即使不能走,因为后面会更新
}
for(i=1; i<=n; i++)
scanf("%d",&cost[i]);
for(k=1; k<=n; k++)
for(i=1; i<=n; i++)
for(j=1; j<=n; j++)
{
s=Edge[i][k]+Edge[k][j]+cost[k];
if(s<Edge[i][j])
{
Edge[i][j]=s;
path[i][j]=path[i][k]; //i到j这条路 i经过k 于是i先到k 所以后继结点变为i到k的后继结点
}
else if(s==Edge[i][j]) //字典序,即可以走k 也可以走i
{
if(path[i][k]<path[i][j]) //走k经过的点比走j小
path[i][j]=path[i][k];
}
}
while(scanf("%d%d",&str,&end)!=EOF&&str!=-1&&end!=-1)
{
printf("From %d to %d :\n",str,end);
printf("Path: %d",str);
k=str; //起点
while(k!=end) //终点是end 依次输出str的后继结点
{
printf("-->%d",path[k][end]);
k=path[k][end];
}
printf("\nTotal cost : %d\n\n",Edge[str][end]);
}
}
return 0;
}