Floyd思想可用下式描述:
A-1[i][j]=gm[i][j]
A(k+1)[i][j]=min{Ak[i][j],Ak[i][k+1]+Ak[K+1][j]} -1<=k<=n-2
该式是一个迭代公式,Ak表示已考虑顶点0,1,.......,k等k+1个顶点之后各顶点之间的最短路径,即Ak[i][j]表示由Vi到Vj已考虑顶点0,1,.......,k等k+1个顶点的最短路径;在此基础上再考虑顶点k+1并求出各顶点在考虑了顶点k+1之后的最短路径,即得到Ak+1.每迭代一次,在从vi到vj的最短路径上就多考虑了一个顶点;经过n次迭代后所得到的A(n-1)[i][j]值,就是考虑所有顶点后从Vi到Vj的最短路径,也就是最终的解。
若Ak[i][j]已经求出,且顶点i到顶点j的路径长度为Ak[i][j],顶点i到顶点k+1的路径长度为Ak[i][k+1],顶点k+1到顶点j的路径长度为Ak[K+1][j],现在考虑顶点k+1,如果Ak[i][K+1]+Ak[k+1][j]<Ak[i][j],则将原来顶点i到顶点j的路径改为:顶点i到顶点k+1,再由顶点k+1到顶点j;对应的路径长度为:A(k+1)[i][j]=Ak[i][k+1]+Ak[k+1][j];否则无需修改顶点i到顶点j的路径.
参考代码:
#include<stdio.h>
#define MAXSIZE 6//带权有向图中顶点的个数
#define INF 32767 void Ppath(int path[][MAXSIZE],int i,int j)//前向递归查找路径上的顶点,MAXSIZE为常数
{
int k;
k=path[i][j];
if(k!=-)
{
Ppath(path,i,k);//找顶点vi的前一个顶点vk
printf("%d->",k);//输出顶点vk序号k
Ppath(path,k,j);//找顶点vk的前一个顶点vj
}
} void Dispath(int A[][MAXSIZE],int path[][MAXSIZE],int n)//输出最短路径的函数
{
int i,j;
for(i=;i<n;i++)
for(j=;j<n;j++)
if(A[i][j]==INF)//INF为一极大常数
{
if(i!=j)
printf("从%d到%d没有路径!\n",i,j);
}
else//从vi到vj有最短路径
{
printf("从%d到%d的路径长度:%d,路径:",i,j,A[i][j]);
printf("%d->",i);//输出路径上的起点序号i
Ppath(path,i,j);//输出路径上的各中间点序号
printf("%d\n",j);//输出路径的终点序号j
}
} void Floyd(int gm[][MAXSIZE],int n)//Floyd算法
{
int A[MAXSIZE][MAXSIZE],path[MAXSIZE][MAXSIZE];
int i,j,k;
for(i=;i<n;i++)
for(j=;j<n;j++)
{A[i][j]=gm[i][j];//A-1[i][j]置初值
path[i][j]=-;//-1表示初始时最短路径不经过中间顶点
}
for(k=;k<n;k++)//按顶点编号k递增的次序查找当前顶点之间的最短路径长度
for(i=;i<n;i++)
for(j=;j<n;j++)
if(A[i][j]>A[i][k]+A[k][j])
{A[i][j]=A[i][k]+A[k][j];//从vi到vj经过vk时路径长度更短
path[i][j]=k;//记录中间顶点Vk的编号
}
Dispath(gm,path,n);//输出最短路径
} void main()
{
int g[MAXSIZE][MAXSIZE]={{INF,,,INF,INF,INF},{,INF,INF,INF,,},{INF,,INF,INF,INF,},
{INF,INF,INF,INF,INF,INF},{INF,INF,INF,,INF,INF},{INF,INF,INF,,,INF}};
Floyd(g,MAXSIZE);
}
输出结果: