Floyd-Warshall算法的运行时间为Θ(V3),它同样允许存在负权边,但假设不存在负权回路。该算法考虑的最优子结构与上述描述类似,即最短路径的子路径是最短路径。但是,它对中间路径的范围加以限制,使其增长与最短路径的最大边数的增长同步。令dij(k)=为从顶点i到顶点j、且满足所有中间顶点属于集合{1,2,…,k}的一条最短路径的权值,定义递归解:如果k=0,dij(k)=wij;如果k≥1,dij(k)=min{ dij(k-1), dik(k-1)+ dkj(k-1)}。可以想象,当k=1时,i到j的最短路径或者由边(i,j)构成,或者由边(i,1)、(1,j)构成。当k=2时,i到j的最短路径可能由子路径i到2和子路径2到j构成,而子路径2到j又可能由边(2,1)、(1,j)构成,即k=2的解包含了k=1的解。以此类推,当k=n时,即可得到每对顶点间最短路径的权值。
为了构造最短路径,定义πij(k)为从i出发的一条最短路径上顶点j的前趋,而这条路径上的中间顶点属于集合{1,2,…,k}。定义πij(k)的递归公式,对于k=0,如果i=j或wij=∞,πij(0) =NIT(-1);如果i≠j和wij<∞,πij(0) =i。对于k≥1,如果dij(k-1)≤dik(k-1)+ dkj(k-1),πij(k) =πij(k-1);如果dij(k-1)>dik(k-1)+ dkj(k-1),πij(k) =πkj(k-1)。
完整的实现代码如下:
完整的实现代码如下:
- #include <iostream>
- #include <string>
- #include <stdio.h>
- using namespace std;
- #define MaxVertexNum 100
- #define INF 32767
- typedef struct
- {
- char vertex[MaxVertexNum];
- int edges[MaxVertexNum][MaxVertexNum];
- int n,e;
- }MGraph;
- void CreateMGraph(MGraph &G)
- {
- int i,j,k,p;
- cout<<"请输入顶点数和边数:";
- cin>>G.n>>G.e;
- cout<<"请输入顶点元素:";
- for (i=0;i<G.n;i++)
- {
- cin>>G.vertex[i];
- }
- for (i=0;i<G.n;i++)
- {
- for (j=0;j<G.n;j++)
- {
- G.edges[i][j]=INF;
- if (i==j)
- {
- G.edges[i][j]=0;
- }
- }
- }
- for (k=0;k<G.e;k++)
- {
- cout<<"请输入第"<<k+1<<"条弧头弧尾序号和相应的权值:";
- cin>>i>>j>>p;
- G.edges[i][j]=p;
- }
- }
- void Dispath(int A[][MaxVertexNum],int path[][MaxVertexNum],int n);
- void Floyd(MGraph G)
- {
- int A[MaxVertexNum][MaxVertexNum],path[MaxVertexNum][MaxVertexNum];
- int i,j,k;
- for (i=0;i<G.n;i++)
- {
- for (j=0;j<G.n;j++)
- {
- A[i][j]=G.edges[i][j];
- path[i][j]=-1;
- }
- }
- for (k=0;k<G.n;k++)
- {
- for (i=0;i<G.n;i++)
- {
- for (j=0;j<G.n;j++)
- {
- if (A[i][j]>A[i][k]+A[k][j])
- {
- A[i][j]=A[i][k]+A[k][j];
- path[i][j]=k;
- }
- }
- }
- }
- Dispath(A,path,G.n);
- }
- void Ppath(int path[][MaxVertexNum],int i,int j)
- {
- int k;
- k=path[i][j];
- if (k==-1)
- {
- return;
- }
- Ppath(path,i,k);
- printf("%d",k);
- Ppath(path,k,j);
- }
- void Dispath(int A[][MaxVertexNum],int path[][MaxVertexNum],int n)
- {
- int i,j;
- for (i=0;i<n;i++)
- {
- for (j=0;j<n;j++)
- {
- if (A[i][j]==INF)
- {
- if (i!=j)
- {
- printf("从%d到%d没有路径/n",i,j);
- }
- }
- else
- {
- printf(" 从%d到%d=>路径长度:%d路径:",i,j,A[i][j]);
- printf("%d,",i);
- Ppath(path,i,j);
- printf("%d/n",j);
- }
- }
- }
- }
- int main()
- {
- MGraph G;
- CreateMGraph(G);
- Floyd(G);
- return 0;
- }