Description
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.
Input
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:
Output
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.
Sample Input
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
3 5
2 4
-1 -1
0
Sample Output
From 1 to 3 :
Path: 1-->5-->4-->3
Total cost : 21
From 3 to 5 :
Path: 3-->4-->5
Total cost : 16
From 2 to 4 :
Path: 2-->1-->5-->4
Total cost : 17
AC代码:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
#define INF 0x3f3f3f3f
#define MAX 2500
int a[MAX][MAX],N;
int path[MAX][MAX],b[MAX];
void Printf(int n,int m)
{
int k;
printf("From %d to %d :\n",n,m);
printf("Path: %d",n);
k=n;
while(k!=m)
{
printf("-->%d",path[k][m]);
k=path[k][m];
}
printf("\nTotal cost : %d\n\n",a[n][m]);
}
void floyd()
{
int i,j,k,len;
for(k=1;k<=N;++k)
for(i=1;i<=N;++i)
for(j=1;j<=N;++j)
{
len = a[i][k]+b[k]+a[k][j];//在中间增加一个k
if(a[i][j]>len)//找到一条更短路则更新
{
a[i][j] = len;
path[i][j] = path[i][k];
}
else if(len==a[i][j])//当相等值时,找字典序最小的,只要比较前一个就行了
{
if(path[i][j]>path[i][k])
{
path[i][j] = path[i][k];
}
}
}
}
int main()
{
/*freopen("input.txt","r",stdin);*/
int n,m,i,j;
while(scanf("%d",&N),N)
{
for(i=1;i<=N;++i)
{
for(j=1;j<=N;++j)
{
scanf("%d",&a[i][j]);
if(a[i][j]==-1)
a[i][j] = INF;
if(i==j)
a[i][j] = 0;
path[i][j] = j;
}
}
for(i=1;i<=N;++i)
scanf("%d",&b[i]);
floyd();
while(scanf("%d%d",&n,&m)&&(n!=-1&&m!=-1))
{
if(n==m)
{
printf("From %d to %d :\n",n,m);
printf("Path: %d",n);
printf("\nTotal cost : 0\n\n");
}
else
Printf(n,m);
}
}
return 0;
}
WA代码:
感觉是字典序里错了。。。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<stack>
using namespace std;
#define INF 0x3f3f3f3f
#define MAX 2500
int a[MAX][MAX],N;
int dis[MAX],path[MAX],bo[MAX],b[MAX],cn[MAX];
stack<int> sta;
void INIT()
{
memset(bo,0,sizeof(bo));
}
void Dijkstra(int n,int m)
{
int i,j,k,mi,u,cnt;
for(i=1;i<=N;++i)
dis[i] = a[n][i],path[i]=0,cn[i]=0;
bo[n] = 1;cnt=1;
while(cnt<=N)
{
cnt++;
mi = INF;
for(i=1;i<=N;++i)
{
if(mi>dis[i]+b[i]&&!bo[i])
mi=dis[i]+b[i],u=i;
}
bo[u]=1;
for(i=1;i<=N;++i)
{
if(!bo[i]&&dis[i]>=mi+a[u][i])
{
dis[i] = mi + a[u][i];
if(cn[i]<cn[u]+1)
{path[i] = u;cn[i] = cn[u] +1;}
}
}
}
printf("From %d to %d :\n",n,m);
printf("Path: ");
k=m;
while(path[k])
{
sta.push(path[k]);
k=path[k];
}
printf("%d-->",n);
while(!sta.empty())
{
printf("%d-->",sta.top());
sta.pop();
}
printf("%d\nTotal cost : %d\n\n",m,dis[m]);
}
int main()
{
/*freopen("input.txt","r",stdin);*/
int n,m,i,j;
while(scanf("%d",&N)&&N)
{
for(i=1;i<=N;++i)
{
for(j=1;j<=N;++j)
{
scanf("%d",&a[i][j]);
if(a[i][j]==-1)
a[i][j] = INF;
}
}
for(i=1;i<=N;++i)
scanf("%d",&b[i]);
while(scanf("%d%d",&n,&m)&&(n!=-1&&m!=-1))
{
INIT();
Dijkstra(n,m);
}
}
return 0;
}