Floyd列印最短路徑及選址問題

2021-10-05 20:47:02 字數 3336 閱讀 8426

前言:在求任意兩點間的最短路問題中,圖一般較為稠密,使用floyd演算法可以在o(n ^ 3)的時間實現。當然也可以把每個點作為起點,求解n次單源最短路徑問題,但較為複雜。這裡介紹floyd演算法以及使用floyd演算法列印路徑和解決選址問題

假設用d[k, i, j]表示「經過若干編號不超過k的結點」從i 到 j的最短路長度,這個問題可以劃分為兩個子問題,經過編號不超過 k - 1 的結點從i到j或者從i 先到k ,再到j,所以有:

d[k, i, j] = min(d[k - 1, i, j], d[k - 1, i, k] + d[k - 1, k, j])

因為一般解決稠密圖,所以使用鄰接矩陣。

floyd演算法的本質是動態規劃,k表示我們所劃分的階段,所以在迴圈的最外層,但我們寫的時候已經將其優化,像揹包問題等動態規劃中那樣,使用「滾動陣列」優化。

所以才有:d[i][j] = min(d[i][j] , d[i][k] + d[k][j]);

給定乙個n個點m條邊的有向圖,圖中可能存在重邊和自環,邊權可能為負數。

再給定k個詢問,每個詢問包含兩個整數x和y,表示查詢從點x到點y的最短距離,如果路徑不存在,則輸出「impossible」。

資料保證圖中不存在負權迴路。

輸入格式

第一行包含三個整數n,m,k

接下來m行,每行包含三個整數x,y,z,表示存在一條從點x到點y的有向邊,邊長為z。

接下來k行,每行包含兩個整數x,y,表示詢問點x到點y的最短距離。

輸出格式

共k行,每行輸出乙個整數,表示詢問的結果,若詢問兩點間不存在路徑,則輸出「impossible」。

資料範圍

1≤n≤200,

1 ≤ k ≤ n2

1 ≤ m ≤20000

圖中涉及邊長絕對值均不超過10000。

輸入樣例:

332

1212

3213

1211

3

輸出樣例:

impossible

1

#include

#include

#include

using

namespace std;

const

int n =

210, inf =

1e9;

int n, m, q;

int d[n]

[n];

void

flody()

intmain()

flody()

;while

(q --

)return0;

}

path[i][j]陣列儲存 i ~ j這條路上 j 前面那個點,假設為k,i ~ j 拆開就是i~ k 和 k ~ j,可以求出k前面的點,遞迴將i ~ j上經過的所有點全部列印出來。

樣例:

451

2113

4231

3411

4614

輸出:

1

->

4的最短路徑為:123

4

#include

#include

#include

using

namespace std;

const

int n =

210, inf =

1e6;

int n, m;

int d[n]

[n],path[n]

[n];

void

init()

;void

floyd()

;void

printpath

(int a,

int b)

;int

main()

floyd()

; cout <<

"請輸入查詢路徑:"

<< endl;

int x, y;

cin >> x >> y;

printf

("%d -> %d的最短路徑為:"

, x, y)

;printpath

(x, y);

cout << endl;

return0;

}void

init()

}void

floyd()

}}void

printpath

(int a,

int b)

int k = path[a]

[b];

printpath

(a, k)

; cout << b <<

" ";

}

比如建造乙個加油站,使所有村莊到加油站的距離最近,問加油站應該建在**。

通過floyd計算出每個點到所有點的最短距離總和,找到總和最小點的就是加油站的位址。

樣例可以自己模擬乙個:

第一行輸入點數n和邊數m

然後m行依次輸入每個點的資訊

#include

#include

#include

using

namespace std;

const

int n =

210, inf =

1e6;

int n, m;

int d[n]

[n];

void

floyd()

;int

main()

floyd()

;int ans = inf;

//存路經總和

int location =0;

//加油站位置

//確定加油站的位置

for(

int i =

1; i <= n; i ++

)}

cout <<

"位置及最短路程總和為:"

; cout << location <<

" "<< ans;

return0;

}void

floyd()

最短路徑 Floyd

簡介 floyd演算法又稱為插點法,是一種利用動態規劃的思想尋找給定的加權圖中多源點之間最短路徑的演算法,與dijkstra演算法類似。該演算法名稱以創始人之一 1978年圖靈獎獲得者 史丹福大學電腦科學系教授羅伯特 弗洛伊德命名。樣例求解 示例 include include using name...

floyd演算法(最短路徑)

最短路徑 描述 已知乙個城市的交通路線,經常要求從某一點出發到各地方的最短路徑。例如有如下交通圖 則從a出發到各點的最短路徑分別為 b 0c 10 d 50 e 30 f 60 輸入 輸入只有乙個用例,第一行包括若干個字元,分別表示各頂點的名稱,接下來是乙個非負的整數方陣,方陣維數等於頂點數,其中0...

最短路徑Floyd演算法

前面我們介紹了單源最短路徑問題的dijkstra演算法,dijkstra演算法雖然有比較好看的複雜度,但其對於有負權值的圖來講,就顯得力不從心了,下面我們來介紹另一種更為廣泛的最短路徑問題的解法 floyd演算法 floyd演算法 弗洛伊德演算法 的原理基於動態規劃,比如要找出從a到b的經過這k個點...