所有节点对的最短路径之Floyd-Warshall

Floyd-Warshall的适用范围

1、求所有节点对的最短路径

2、边的权重可以为负

3、不能存在负环路

Floyd-Warshall算法的描述

Floyd-Warshall实际上是一种动态规划的思想。假如图中有n个节点,编号为1~n,我们令d[k][i][j]表示只能使用1~k号节点作为中间节点时,节点i到j的最短路径距离。d[0][i][j]表示没有中间节点时,i到j的最短路径距离,d[1][i][j]表示只能有节点1作为中间节点时,i到j的最短路径长度。d[k][i][j]可以分为两种情况:

1、节点k在i到j的最短路径上,此时d[k][i][j]=d[k-1][i][k]+d[k-1][k][j]

2、节点k不在i到j的最短路径上,此时d[k][i][j]=d[k-1][i][j]

所以d[k][i][j]=min{d[k-1][i][j],d[k-1][i][k]+d[k-1][k][j]}

floyd的java模板

	int n;//节点的总个数
	int d[][][];//d[k][i][j]:能使用1~k号节点作为中间节点时,节点i到j的最短路径距离
	int w[][];//w[i][j]:边(i,j)的权重,若i,j之间没有边,则令w[i][j]=MAX,若i==j,则w[i][j]=0
	int MAX=0xfffff;//很大的一个数,用来表示两个节点之间没有边
	void floyd()
	{
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				d[0][i][j]=w[i][j];
			}
		}
		for(int k=1;k<=n;k++)
		{
			for(int i=1;i<=n;i++)
			{
				for(int j=1;j<=n;j++)
				{
					if(i==j) continue;
					d[k][i][j]=Math.min(d[k-1][i][j], d[k-1][i][k]+d[k-1][k][j]);
				}
			}
			
		}
	}


通过观察动态转移方程d[k][i][j]=min{d[k-1][i][j],d[k-1][i][k]+d[k-1][k][j]},我们可以发现k阶段的状态(d[k][i][j]),只与k-1阶段的转态(d[k-1]..)的状态有关,我们可以将上面的代码简化成

floyd简化版java模板

	int n;//节点的总个数
	int d[][];//d[i][j]:表示当前求得的i到j的最短路径距离
	int w[][];//w[i][j]:边(i,j)的权重,若i,j之间没有边,则令w[i][j]=MAX,若i==j,则w[i][j]=0
	int MAX=0xfffff;//很大的一个数,用来表示两个节点之间没有边
	void floyd()
	{
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				d[i][j]=w[i][j];
			}
		}
		for(int k=1;k<=n;k++)
		{
			for(int i=1;i<=n;i++)
			{
				for(int j=1;j<=n;j++)
				{
					if(i==j) continue;
					if(d[i][j]>d[i][k]+d[k][j])
					{
						d[i][j]=d[i][k]+d[k][j];
					}
				}
			}
			
		}
	}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值