获得所有顶点间的最短路,可以对每个顶点做dijkstra或者bellman,但是dijkstra麻烦而且不能有负边存在,bellman又复杂度太大。Floyd解决多元最短路很直观。
其基本思想是:对一个顶点个数为n的网,设置一个n*n的方阵A(k),A(k)[i][j](i!=j)表示从顶点vi到vj的有向路径长度,k表示运算步骤。
初始化后,在原路径中加入其他顶点作为中间顶点,更新之。
递推公式:
A(-1)[i][j]=Edge[i][j]
A(k)[i][j]=min{A(k-1)[i][j],A(k-1)[i][k]+A(k-1)[k][j]},k=0,1,2,……,n-1;
时间复杂度为O(n^3)。
和bellman很像。。。Floyd是用了A[][]来保存路径了。
下面实现代码里的For(k=0;k<n;k++)可以看成是依次将v0,v1,.....v(n-1) 作为中间顶点。
//floyd实现代码:
#include <cstdio>
#include <iostream>
#include <sstream>
#include <cstring>
#include <cmath>
#include <string>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <algorithm>
#define INF 1023123123
#define EPS 1e-11
#define MAXN 8
using namespace std;
int n;
int Edge[MAXN][MAXN];
int A[MAXN][MAXN],path[MAXN][MAXN];
void floyd()
{
int i,j,k;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
A[i][j]=Edge[i][j];//init for A[][]
if(i!=j&&A[i][j]<INF) path[i][j]=i;
else path[i][j]=-1;//no direct distant
}
}
for(k=0;k<n;k++)//k is temp
{
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
if(k==i||k==j) continue;//not need todo
if(A[i][k]+A[k][j]<A[i][j])
{
A[i][j]=A[i][k]+A[k][j];
path[i][j]=path[k][j];
}
}
}
}
}
int main()
{
int i,j;
int u,v,w;
cin>>n;
for(i=0;i<n;i++)
for(j=0;j<n;j++)
Edge[i][j]=INF;
for(i=0;i<n;i++)
Edge[i][i]=0;
while(cin>>u>>v>>w)
{
if(u==-1&&v==-1&&w==-1) break;
Edge[u][v]=w;
}
floyd();
int shortest[MAXN];
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
if(i==j) continue;
cout<<i<<"=>"<<j<<"\t"<<A[i][j]<<"\t";
reset(shortest,0);
int k=0;
shortest[k]=j;
while(path[i][shortest[k]]!=i)//final point
{
k++;
shortest[k]=path[i][shortest[k-1]];
}
k++;
shortest[k]=i;
for(int t=k;t>0;t--)
cout<<shortest[t]<<"->";
cout<<shortest[0]<<endl;
}
}
return 0;
}
/*
4
0 1 1
0 3 4
1 2 9
1 3 2
2 0 3
2 1 5
2 3 8
3 2 6
-1 -1 -1
*/