书上把这放在了bellman,但我觉得用floyd应该更加好写些
注意一个坑人的地方,就是测试数据中有自己到自己,输出是单独的n,而不是n-->n
/*
author:jxy
lang:C/C++
university:China,Xidian University
**If you need to reprint,please indicate the source**
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#define maxn 100
using namespace std;
int dis[maxn][maxn],p[maxn],n;
queue<int> q;
int d[maxn];
int near[maxn];
bool inq[maxn];
int way[2][maxn],K[2];
void path(int now,bool f)
{
if(near[now]==now)return;
else
{
path(near[now],f);
way[f][K[f]++]=now;
}
}
bool cmp(int a,int b,int c)//生成路径比较字典序大小
{
K[0]=K[1]=0;
path(a,0);
path(b,1);
way[0][K[0]++]=c;
way[1][K[1]++]=c;
int i;
for(i=0;way[0][i]+way[1][i];i++)
{
if(way[0][i]>way[1][i])return 0;
if(way[0][i]<way[1][i])return 1;
}
return 0;
}
int bellman(int v,int aim)
{
if(aim==v)return 0;
while(!q.empty())q.pop();
for(int i=0;i<=n;i++)
{
near[i]=i;
inq[i]=0;
d[i]=100000000;
}
d[v]=0;q.push(v);
int now,next,t;
while(!q.empty())
{
now=q.front();q.pop();
inq[now]=0;
for(next=1;next<=n;next++)
{
if(next==now||next==v)continue;//防止产生环
if(dis[now][next]!=-1&&(d[next]>(t=d[now]+dis[now][next]+p[now])||(d[next]==t&&cmp(now,near[next],next))))
{
d[next]=t;
near[next]=now;
if(inq[next])continue;
q.push(next);
inq[next]=1;
}
}
}
return d[aim]-p[v];
}
int main()
{
while(~scanf("%d",&n)&&n)
{
int i,j;
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
scanf("%d",&dis[i][j]);
for(i=1;i<=n;i++)
scanf("%d",&p[i]);
int v,u,t;
while(~scanf("%d%d",&v,&u))
{
if(v==-1||u==-1)break;
t=bellman(v,u);
printf("From %d to %d :\n",v,u);
printf("Path: %d",v);
K[0]=0;
if(u!=v)
{
path(u,0);
for(int i=0;i<K[0];i++)
printf("-->%d",way[0][i]);
}
printf("\nTotal cost : %d\n\n",t);
}
}
}