1. 程式人生 > >Folyd演算法(轉+適合問題 )

Folyd演算法(轉+適合問題 )

 Folyd演算法適合多源最短路的求解問題(時間複雜度(O(n^3)),單源無負權值的問題適合Dijstra(O(n^2))

小Hi強行裝作沒聽到,繼續說道:“這個演算法的核心之處在於數學歸納法——MinDistance(i, j)之間最短路徑中可以用到的節點是一點點增加的!”

“你這話每一個字我都聽得懂,但是這句話為什麼我聽不懂呢……”小Ho無奈道。

“那我這麼說吧,首先,最開始的時候,MinDistance(i, j)——即從第i個點到第j個點的最短路徑的長度,擁有一個限制:這條路徑不能經過任何節點。”小Hi道。

“那就是說如果從i個點到第j個點之間沒有直接相連的邊的話,這個長度就是無窮大咯?”小Ho總結道:“只需要把輸入的邊填進MinDistance中即可!”

“對!”小Hi滿意於小Ho的上道,繼續說道:“然後我放開限制,我允許MinDistance(i, j)——從第i個點到第j個點的最短路徑的長度,擁有的限制,變為:這條路徑僅允許經過1號節點。”

“這個也簡單,對於兩個節點i, j,我只需要比較MinDistance(i, j)原來的值和MinDistance(i, 1)+MinDistance(1, j)的值,取較小的一個作為新的MinDistance(i, j)就可以了——畢竟原來的MinDistance都是不經過任何節點,那麼這樣求出來的新的MinDistance(i, j)只有可能經過1號節點。”

“那麼接下來就是關鍵的了,我將限制繼續放寬——路徑僅允許經過1、2號節點。”小Hi繼續說道。

“那其實也沒有任何變化吧,對於兩個節點i, j,我只需要比較MinDistance(i, j)原來的值和MinDistance(i, 2)+MinDistance(2, j)的值,取較小的一個作為新的MinDistance(i, j),之所以可以這樣是因為,原來的MinDistance都是在限制“僅允許經過1號節點”下,求出來的,所以新求出來的MinDistance(i, j)也只有可能經過1、2號節點!“

“那我繼續放開限制呢?”小Hi問道。

“也沒有什麼區別了,每放開一個新的節點k允許作為路徑中的節點,就對於任意的i, j,用MinDistance(i, k)+MinDistance(k, j)去更新MinDistance(i, j),直到1..N號節點都被新增進限制,此時也就等於沒有限制了,那麼這個時候的MinDistance(i, j)就是我們所想要求的值
 


//輸入邊的時候一定要注意重邊的選擇問題

	/*

	int u, v, c; scanf("%d %d %d", &u, &v, &c);

	dis[u][v] = dis[v][u] = min(dis[u][v], c);

	*/

	for (int k = 1; k <= n; k++){

		for (int i = 1; i <= n; i++){

			for (int j = 1; j <= n; j++){

				dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);

			}

		}

	}