http://acm.hdu.edu.cn/showproblem.php?pid=1385
#include <iostream>
#include <algorithm>
#define MAX 1000
using namespace std;
int map[MAX+10][MAX+10]; //map[i][j]表示从i到j路上的花费
int tax[MAX+10]; //每个城市的过路费
int path[MAX+10][MAX+10]; //path[i][j]记录经过从i到j经过的第一个城市
int n; //城市数
void floyd(){
int i,j,k;
for(k=1;k<=n;k++)
for(i=1;i<=n;i++)
for(j=1;j<=n;j++){
if(map[i][k]!=-1&&map[k][j]!=-1){
if(map[i][j]==-1||map[i][j]>map[i][k]+tax[k]+map[k][j]){
map[i][j]=map[i][k]+tax[k]+map[k][j];
//更改路径
path[i][j]=path[i][k];
}
else if(map[i][j]==map[i][k]+tax[k]+map[k][j]){
//实现字典序
if(path[i][j]>path[i][k]&&k!=i){ //开始写成了if(k<j&&k!=i)导致一直wa
//更改路径
path[i][j]=path[i][k];
}
}
}
}
}
//输出路径
void findPath(int a,int b){
cout<<a<<"-->";
int j=path[a][b];
while(j!=b){
cout<<j<<"-->";
j=path[j][b];
}
cout<<b<<endl;
}
int main()
{
int i,j;
memset(path,0,sizeof(path));
while(scanf("%d",&n)&&n)
{
for(i=1;i<=n;i++){
for(j=1;j<=n;j++){
scanf("%d",&map[i][j]);
if(map[i][j]!=-1)
//初始从i到j经过的第一个城市为j
path[i][j]=j;
}
}
for(i=1;i<=n;i++)
scanf("%d",&tax[i]);
floyd();
//求a,b之间的最少花费,以及该最少花费经过的城市
int a,b;
while(scanf("%d%d",&a,&b)){
if(a==-1&&b==-1)
break;
cout<<"From "<<a<<" to "<<b<<" :"<<endl;
printf("Path: ");
if(a==b) cout<<a<<endl;
else
findPath(a,b);
printf("Total cost : %d\n\n",map[a][b]);
}
}
return 0;
}