FLOYD 多源最短路

获得所有顶点间的最短路,可以对每个顶点做dijkstra或者bellman,但是dijkstra麻烦而且不能有负边存在,bellman又复杂度太大。Floyd解决多元最短路很直观。

其基本思想是:对一个顶点个数为n的网,设置一个n*n的方阵A(k),A(k)[i][j](i!=j)表示从顶点vivj的有向路径长度,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;

时间复杂度为On^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
*/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值