这个字典序不是很难就是注意一下最短路相等的时候路径的跟新就好了;
具体解析见代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define INF 1000000
using namespace std;
int map[55][55];//记录城市与城市之间的距离
int step[550];//记录路径
int cost[55];//记录经过城市的时候所需的税收
int mincost[55];//记录最短路
int n;//城市数
int judge[55];//这个就不解释了;
int star,end;//起点与终点
void output(int s, int target)//输出
{
printf("Path: ");
int t=s;
printf("%d",t);
while(true)
{
t=step[t];
if(t==-1) break;
printf("-->%d",t);
}
printf("\n");
if(s!=target)
printf("Total cost : %d\n",mincost[s]);
if(s==target)
printf("Total cost : 0\n");
printf("\n");//这个少些了会PE
return;
}
void solve(int s,int f)//DIJI算法主体
{
memset(judge,0,sizeof(judge));
memset(step,-1,sizeof(step));
for(int i=0;i<=n;i++) mincost[i]=INF;
//mincost[s]=0;
mincost[f]=0;
while(1)
{
int x=-1;
for(int i=1;i<=n;i++)
{
if(judge[i]==0&&(x==-1||mincost[i]<mincost[x])) x=i;
}
if(x==-1) break;
judge[x]=1;
for(int i=1;i<=n;i++)
{
if(mincost[i]>map[i][x]+mincost[x]+cost[x])
{
step[i]=x;
mincost[i]=map[i][x]+mincost[x]+cost[x];
}
else if(mincost[i]==map[i][x]+mincost[x]+cost[x])//就用这个IF搞定字典序输出的问题
{
if(step[i]==-1||step[i]>x)
step[i]=x;
}
}
}
mincost[s]-=cost[f];//因为并未经过终点所以要把终点的税收减去;
output(s,f);
}
int main()
{
while(scanf("%d",&n)!=EOF&&n)
{
memset(map,-1,sizeof(map));
memset(cost,0,sizeof(cost));
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
scanf("%d",&map[i][j]);
if(map[i][j]==-1) map[i][j]=INF;//用INF代替-1,方便一些
}
}
for(int i=1;i<=n;i++) scanf("%d",&cost[i]);
/*for(int i=1;i<=n;i++)
{
printf("%d %d\n",i,cost[i]);
}*/
while(true)
{
scanf("%d%d",&star,&end);
if(star==-1&&end==-1) break;
printf("From %d to %d :\n",star,end);
solve(star,end);
}
}
return 0;
}
看见网上有人用二维数组标记路径,死活没看懂。。。。。。
不过还好我就的我的方法真的很实用。