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;
}

運行結果:



發佈了56 篇原創文章 · 獲贊 105 · 訪問量 16萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章