题目描述
These are N cities in Spring country. Between each pair of cities there may be one transportation track or none. Now there is some cargo that should be delivered from one city to another. The transportation fee consists of two parts:
The cost of the transportation on the path between these cities, and
a certain tax which will be charged whenever any cargo passing through one city, except for the source and the destination cities.
You must write a program to find the route which has the minimum cost.
输入格式
First is N, number of cities. N = 0 indicates the end of input.
The data of path cost, city tax, source and destination cities are given in the input, which is of the form:
a11 a12 … a1N
a21 a22 … a2N
…
aN1 aN2 … aNN
b1 b2 … bN
c d
e f
…
g h
where aij is the transport cost from city i to city j, aij = -1 indicates there is no direct path between city i and city j. bi represents the tax of passing through city i. And the cargo is to be delivered from city c to city d, city e to city f, …, and g = h = -1. You must output the sequence of cities passed by and the total cost which is of the form:输出格式
From c to d :
Path: c–>c1–>…–>ck–>d
Total cost : …
…
From e to f :
Path: e–>e1–>…–>ek–>f
Total cost : …
Note: if there are more minimal paths, output the lexically smallest one. Print a blank line after each test case.输入样例
5
0 3 22 -1 4
3 0 5 -1 -1
22 5 0 9 20
-1 -1 9 0 4
4 -1 20 4 0
5 17 8 3 1
1 3
-1 -1
0输出样例
From 1 to 3 :
Path: 1–>5–>4–>3
Total cost : 21
分析
题目大意是有n个城市,经过任意一个城市不仅要交税,还要路线上的运输费用, 现在要求从a城市到b城市的最小费用,以及最下距离下的按字典序的路径。考虑到题目中有多组查询,因此使用floyd算法,另外由于需要字典序最小路径,就需要后驱存储,因为前驱存储无法保证字典序,以下是源码。
源程序
Floyd算法
#include <bits/stdc++.h>
#define MAXN 105
#define INF 1e9
using namespace std;
int n,x,y,g[MAXN][MAXN],point[MAXN],path[MAXN][MAXN];
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][k]==INF||g[k][j]==INF)continue; //不存在边
int tmp=g[i][k]+g[k][j]+point[k];
if(g[i][j]>tmp){ //新的最小值
g[i][j]=tmp;
path[i][j]=path[i][k];
}
else if(g[i][j]==tmp&&path[i][j]>path[i][k]){ //最小值相等但从i出发的路径更小
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",&g[i][j]);
if(g[i][j]==-1)g[i][j]=INF;
path[i][j]=j; //初始化path数组
}
}
for(int i=1;i<=n;i++)scanf("%d",&point[i]); //读入点数
floyd();
while(scanf("%d%d",&x,&y)){
if(x==-1&&y==-1) break;
printf("From %d to %d :\n",x,y);
printf("Path: ");
int u=x;
printf("%d",u);
while(u!=y){ //后驱
printf("-->%d",path[u][y]);
u=path[u][y];
}
printf("\nTotal cost : %d\n\n", g[x][y]);
}
}
}