dijkstra 演算法是處理單源最短路徑的有效演算法,但它對存在負權迴路的圖就會失效。這時候,就需要使用其他的演算法來應對這個問題,bellman-ford(中文名:貝爾曼-福特)演算法就是其中乙個。
bellman-ford 演算法不僅可以求出最短路徑,也可以檢測負權迴路的問題。該演算法由美國數學家理查德•貝爾曼(richard bellman, 動態規劃的提出者)和小萊斯特•福特(lester ford)發明。
對於乙個不存在負權迴路的圖,bellman-ford 演算法求解最短路徑的方法如下:
設其頂點數為 n,邊數為 m。設其源點為 source,陣列dist[i]
記錄從源點 source 到頂點i的最短路徑,除了dist[source]
初始化為 0 外,其它dist
皆初始化為 int_max。以下操作迴圈執行 n-1 次:
n-1 次迴圈,bellman-ford 演算法就是利用已經找到的最短路徑去更新其它點的dist
。
接下來再看看 bellman-ford 演算法是如何檢測負權迴路的?
檢測的方法很簡單,只需在求解最短路徑的 n-1 次迴圈基礎上,再進行第 n 次迴圈:
迴圈次數
dist[0]
dist[1]
dist[2]
第1次0
-5-3
第2次-2
-5-3
第3次-2
-7-5
#include #include using namespace std;
struct edge
;edge edge[10000]; // 記錄所有邊
int dist[100]; // 源點到頂點 i 的最短距離
int path[100]; // 記錄最短路的路徑
int vertex_num; // 頂點數
int edge_num; // 邊數
int source; // 源點
bool bellmanford()
} }bool flag = true; // 標記是否有負權迴路
// 第 n 次迴圈判斷負權迴路
for (int i = 0; i < edge_num; i++) }
return flag;
}void print()
cout << "--" << source << endl;
} }}int main()
測試如下:
/* test 1 */
請輸入圖的頂點數,邊數,源點:5 7 0
請輸入 7 條邊的資訊:
0 1 100
0 2 30
0 4 10
2 1 60
2 3 60
3 1 10
4 3 50
0 到 1 的最短距離是:70,路徑是:1--3--4--0
0 到 2 的最短距離是:30,路徑是:2--0
0 到 3 的最短距離是:60,路徑是:3--4--0
0 到 4 的最短距離是:10,路徑是:4--0
/* test 2 */
請輸入圖的頂點數,邊數,源點:4 6 0
請輸入 6 條邊的資訊:
0 1 20
0 2 5
3 0 -200
1 3 4
3 1 4
2 3 2
存在負權迴路!
以下除非特殊說明,否則都預設是不存在負權迴路的。
先來看看 bellman-ford 演算法為何需要迴圈 n-1 次來求解最短路徑?
讀者可以從 dijkstra 演算法來考慮,想一下,dijkstra 從源點開始,更新dist
,找到最小值,再更新dist
,,,每次迴圈都可以確定至少乙個點的最短路。bellman-ford 演算法同樣也是這樣,它的每次迴圈也可以確定至少乙個點的最短路,故需要 n-1 次迴圈。
bellman-ford 演算法的時間複雜度為 \(o(nm)\),其中 n 為頂點數,m 為邊數。每一次迴圈都需要對 m 條邊進行操作,\(o(nm)\) 的時間,其實大多數都浪費了。
大家可以考慮乙個隨機圖(點和邊隨機生成),除了已確定最短路的頂點與尚未確定最短路的頂點之間的邊,其它的邊所做的都是無用的,大致描述為下圖(分割線以左為已確定最短路的頂點),
其中紅色部分為所做無用的邊,藍色部分為實際有用的邊。
既然只需用到中間藍色部分的邊,那演算法優化的方向就找到了,請接著看本系列第三篇文章:spfa 演算法。
單源最短路徑
include define max 999 define maxverts 10 typedef struct graph void chushi graph g void dij graph int key,int int int main for i 1 i g.numverts i dij ...
單源最短路徑
最優子結構 最短路徑的子路徑也是最短路徑,動態規劃和貪心演算法的乙個重要指標。環路 一條最短路徑不可能包含環路 1 環路權重為負,如果有一條環路權重為負,則不存在最短路徑 2 環路權重為零,如果包含該環路,則將該環路去掉即可 3 環路權重為正,去掉改環路可以得到更短的路徑,因此不可能是最短路徑 最短...
單源最短路徑
單源最短路徑問題,即在圖中求出給定頂點到其他任一頂點的最短路徑。1.最短路徑的最優子結構性質 該性質描述為 如果p i,j 是從頂點i到j的最短路徑,k和s是這條路徑上的乙個中間頂點,那麼p k,s 必定是從k到s的最短路徑。證明 假設p i,j 是從頂點i到j的最短路徑,則有p i,j p i,k...