http://acm.hdu.edu.cn/showproblem.php?pid=1385
是一道典型的floyd,但需要输出路径(而且是字典序最小的路径),这题难就难在这两点上了.
分析:典型的floyd,这里使用path数组来记录路径,path[a][b]表示a到b的所有路径中的与a最近的一个
结点,path[a][a]则记录当前结点a。另外题目要求按字典序输出结果,只要判断当路径权值相同时,更新结点值小的那个路径即可!
解决了以上两个问题,这就成了水题:
#include<cstdio>
#include<algorithm>
using namespace std;
#define INF 0x3f3f3f3f
const int N=1000+10;
int nnum,cost[N],path[N][N],map[N][N];
//map[a][b]存放a到b的最短路
void floyd()
{
for(int i=1;i<=nnum;i++)
for(int j=1;j<=nnum;j++)
path[i][j]=j;//(路径记录)这里记录路径的方法非常不错
for(int k=1;k<=nnum;k++)//floyd算法
for(int i=1;i<=nnum;i++)
for(int j=1;j<=nnum;j++)
{
int temp=map[i][k]+map[k][j]+cost[k];//(+cost[k]一般没有)
if(temp<map[i][j])
{
map[i][j]=temp, path[i][j]=path[i][k];//记录当前路径
}
else if(temp==map[i][j])//如果最短路有多条
{
if(path[i][j]>path[i][k]) path[i][j]=path[i][k];//按路径的字典序输出!
}
}//floyd算法
}
int main()
{
read, write;
while(scanf("%d",&nnum)!=EOF && nnum)
{
for(int i=1;i<=nnum;i++)
for(int j=1;j<=nnum;j++)
{
scanf("%d",&map[i][j]);
if(map[i][j]==-1) map[i][j]=INF;//按邻接矩阵输入图
}
for(int i=1;i<=nnum;i++) scanf("%d",&cost[i]);//可无
floyd();//进行运算
int a,b;//求解a、b两点之间的最短路
while(scanf("%d%d",&a,&b)!=EOF && a!=-1 && b!=-1)
{
printf("From %d to %d :/n",a,b);
printf("Path: %d",a);
int xx=a;
while(xx!=b)
{
printf("-->%d",path[xx][b]);
xx=path[xx][b];
}
printf("/nTotal cost : %d/n/n",map[a][b]);
}
}
return 0;
}