Minimum Transport Cost
题意:给出一张图的邻接矩阵,k个询问,每次输出 x 到 y 的最短路径的长度,和字典序最小的路径。
经典套路: p a t h [ i ] [ j ] path[i][j] path[i][j] 存从 i i i 到 j j j 的最短路中要经过的第一个点( i i i除外)。具体见注释。
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<cstdio>
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 210;
int dis[N][N];
int path[N][N];
int w[N];
int n,m;
void floyd()
{
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
int t = dis[i][k]+dis[k][j]+w[k]; //起点和终点不需要代价
if(t < dis[i][j]){
dis[i][j] = t;
path[i][j] = path[i][k]; //从i到j的第一个点更新为i到k的第一个点点
}
else if(t == dis[i][j]) //当距离相同时取较小字典序
path[i][j] = min(path[i][j],path[i][k]);
}
}
int main()
{
while(scanf("%d",&n)&&n){
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) {
scanf("%d",&dis[i][j]);
if(dis[i][j]==-1) dis[i][j]=INF; //初始化不可达
path[i][j] = j; //初始化路径
}
for(int i=1;i<=n;i++) scanf("%d",&w[i]);
floyd();
int x,y;
while(scanf("%d%d",&x,&y)){
if(x==-1&&y==-1) break;
int ans = dis[x][y];
printf("From %d to %d :\n",x,y);
printf("Path: ");
while(x!=y){ //注意起点和终点相同的情况
printf("%d-->",x);
x = path[x][y];
}
printf("%d\n",y);
printf("Total cost : %d\n\n",ans);
}
}
return 0;
}