floyd求最短路径长度

floyd算法是非单源最短路算法的一种;非单源即算法运行一次,可求出任意节点至任意可到达节点的最短路长度,其时间复杂度为O(n^3)。

相较于单源算法dijkstra求最短路,floyd有更简洁的代码。关于dijkstra求最短路长度,请点击这里;如果你还想记录dijkstra最短路的路径,请点击这里


floyd的思想,即从图中每次取出一个节点作为中途节点,看经过该中途节点,任意两节点间是否具有更小的距离,有则更新;算法在将所有节点均作为过中途节点之后结束。

下面有两个问题:



1. 将任意一条通路取出拉直后就如图一所示,我们想知道用floyd最终能否产生AD的直接通路?(直接通路即节点间有弧直接连接,非科学定义)

最初,图中只有AB,BC,CD三条通路。如果先将C作为中途节点,那么由BC和CD将产生BD这条直接通路。接着再以节点B作为中途节点,由AB和BC产生直接通路AC,由AB和BD(BD刚刚产生)会产生直接通路AD。即使打乱中途节点的顺序,最终仍会获得AD这条直接通路。

所以无论谁先作为中途节点,只要将所有节点均作为过中途节点之后,原本连通的节点之间一定会产生直接通路。


2. 我们想知道用floyd求出图二的AD直接通路长度一定是从A到D的最短长度吗?

最初,图中有AE=5,AB=10,EC=5,BC=10,CD=10这五条直接的通路。如果先将B作为中途节点,则通过AB和BC产生AC=20这条直接通路。再以节点C作为中途节点,则通过EC和CD产生直接通路ED=15,通过BC和CD产生直接通路BD=20,通过AC(AC刚刚产生)和CD产生直接通路AD=30。再以节点E作为中途节点,可由AE和EC得到直接通路AC=10(小于原有的AC=20,更新),再由AE和ED得到直接通路AD=20(小于原有的AD=30,更新)。

所以无论谁先作为中途节点,只要将所有节点均作为过中途节点之后,则所有直接通路的长度定是这两个节点间的最短路长度。


下面是求图3所有节点之间最短路长度的代码(floyd):

#include<stdio.h>
const int INF=10000;        //INF表示无穷大,这里假设为10000
const int N=100;
int p[N][N];                //p表示各节点间的距离,不存在路径即为无穷大

void floyd(int n)           //n表示节点总数
{
	int i,j,k;
	for(k=0;k<n;k++)        //k表示中途节点,每次将一节点作为中途节点后,都需要更新所有节点之间的最短长度
	{
		for(i=0;i<n;i++)    //i表示出发节点
		{
			for(j=0;j<n;j++)//j表示结束节点
			{
				if(p[i][j]>p[i][k]+p[k][j])
				{
					p[i][j]=p[i][k]+p[k][j];//如果节点i到节点j经过节点k有更短的长度,则更新
				}
			}
		}
	}
}
int main()
{
    int i,j,n=5;             //n表示节点总数
    for(i=0;i<n;i++)
    {
        for(j=0;j<n;j++)
        {
            p[i][j]=i==j?0:INF;//初始化:i到j路径为无穷大或者i到i本身为0  
        }
    }
    p[0][1]=10;p[0][3]=30;p[0][4]=100;p[1][2]=50;p[2][4]=50;p[3][2]=20;p[3][4]=60;//p[i][j]表示节点i到节点j的距离
	floyd(n);
	for(i=0;i<n;i++)         //打印所有节点之间的最短路长度
	{
		for(j=0;j<n;j++)
		{
			printf(j==n-1?"%d=>%d:%-5d\n":"%d=>%d:%-5d ",i,j,p[i][j]);
		}
		printf("\n");
	}
    return 0;
}

运行结果:



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值