【题意】题意就是说过某个村庄时需要给一定的费用,且路上也是需要给钱的,问如何才能使从村庄A运送货物到B花的费用最少,且字典序最小。
【分析】典型的多维最短路,优先考虑费用的为题,再费用相同时再考虑字典序的问题,这里的字典序指的是经过的村庄的编号先后构成的一个序列。这样的话,状态就应该含有费用,路径两个信息(结构体),然后进行状态转移。
【路径记录】path【i】【j】代表从i到j不包含i,j的第一个顶点。
【核心】优先更新路径长度,其次是字典序。
【AC代码】
#include <stdio.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 102;
int G[maxn][maxn],path[maxn][maxn],cost[maxn];
int i,j,k,s,e,n;
void Floyd()
{
for(k=1; k<=n; k++)
{
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
int cur=G[i][k]+G[k][j]+cost[k];
if(cur<G[i][j])G[i][j]=cur,path[i][j]=path[i][k];
else if(cur==G[i][j]){
if(path[i][j]>path[i][k]){
path[i][j]=path[i][k];
}
}
}
}
}
}
int main()
{
while(~scanf("%d",&n)&&n)
{
int data;
for(int i=1; i<=n; i++)
{
for(int j=1; j<=n; j++)
{
scanf("%d",&data);
if(data==-1)G[i][j]=INF;
else G[i][j]=data;
path[i][j]=j;
}
}
for(int i=1; i<=n; i++)scanf("%d",&cost[i]);
Floyd();
while(~scanf("%d%d",&s,&e))
{
if(s==-1&&e==-1)break;
printf("From %d to %d :\n",s,e);
printf("Path: %d",s);
int temp=s;
while(temp!=e)
{
temp = path[temp][e];
printf("-->%d",temp);
}
printf("\nTotal cost : %d\n\n",G[s][e]);
}
}
return 0;
}