Froyd-Warshall算法用于求解所有点对之间的最短距离,其中权值可以为负值,但是不能有负数的环。时间复杂度为O(n^3)。
该算法的思路是,
第一步:所有从 i 到 j 的最短路径为i、j之间的权值(不相连的话就设为某个MAX数值)
第二步:如果结点数为 n, 对 n 从 1 到 n,每次假设加入一个结点后,那么 i 与 j之间的最短距离要么还是原来的值,要么是新结点加入后,通过新结点的“新”最短路径修正的值。即状态转移方程为:
其中上标 k 表示最短路径经过的结点属于集合{1,2,3,...,k}
#include <iostream>
#include <string>
#include <stdio.h>
using namespace std;
#define MaxVertexNum 100
#define INF 10000
typedef struct
{
char vertex[MaxVertexNum];
int edges[MaxVertexNum][MaxVertexNum];
int n,e;
}MGraph;
void CreateMGraph(MGraph &G)
{
int i,j,k,p;
cout<<"请输入顶点数和边数:"<<endl;
cin>>G.n>>G.e;
cout<<"请输入顶点元素:"<<endl; //用A、B、C等来表示顶点
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<<"条边的首尾顶点和相应的权值:"<<endl;
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; //如果没有中间结点,则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])
//如果INF被定义为INT_MAX的话,要注意加法不要溢出
{
A[i][j]=A[i][k]+A[k][j];
path[i][j]=k;
//注意,k记录的是最短路径中顶点标号最大的那个数,因此在下面的Ppah函数中要分别递归
}
}
}
}
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()
{
/*freopen("input.txt", "r", stdin);*/
MGraph G;
CreateMGraph(G);
Floyd(G);
return 0;
}