floyd求最短路径长度

来源:互联网 发布:mac虚拟机装win7 编辑:程序博客网 时间:2024/05/21 18:42

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表示无穷大,这里假设为10000const 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;}

运行结果:



0 0
原创粉丝点击