Bellman-Ford算法——爲何要循環n-1次?圖有n個點,又不能有迴路,因此最短路徑最多n-1邊。又由於每次循環,至少relax一邊因此最多n-1次就好了!

單源最短路徑python

給定一個圖,和一個源頂點src,找到從src到其它全部全部頂點的最短路徑,圖中可能含有負權值的邊。算法

Dijksra的算法是一個貪婪算法,時間複雜度是O(VLogV)(使用最小堆)。可是迪傑斯特拉算法在有負權值邊的圖中不適用,Bellman-Ford適合這樣的圖。在網絡路由中,該算法會被用做距離向量路由算法。Bellman-Ford也比迪傑斯特拉算法更簡單。但Bellman-Ford的時間複雜度是O(VE),這要比迪傑斯特拉算法慢。(V爲頂點的個數,E爲邊的個數)spring

算法描述網絡

輸入:圖 和 源頂點
輸出:從src到全部頂點的最短距離。若是有負權迴路(不是負權值的邊),則不計算該最短距離,沒有意義,由於能夠穿越負權迴路任意次,則最終爲負無窮。app

算法步驟spa

1.初始化:將除源點外的全部頂點的最短距離估計值 dist[v] ← +∞, dist[s] ←0;
2.迭代求解:反覆對邊集E中的每條邊進行鬆弛操做,使得頂點集V中的每一個頂點v的最短距離估計值逐步逼近其最短距離;(運行|v|-1次)
3.檢驗負權迴路:判斷邊集E中的每一條邊的兩個端點是否收斂。若是存在未收斂的頂點,則算法返回false,代表問題無解;不然算法返回true,而且從源點可達的頂點v的最短距離保存在 dist[v]中。code

關於該算法的證實也比較簡單,採用反證法,具體參考:http://courses.csail.mit.edu/6.006/spring11/lectures/lec15.pdf
該算法是利用動態規劃的思想。該算法以自底向上的方式計算最短路徑。
它首先計算最多一條邊時的最短路徑(對於全部頂點)。而後,計算最多兩條邊時的最短路徑。外層循環須要執行|V|-1次。blog

例子圖片

一下面的有向圖爲例:給定源頂點是0,初始化源頂點距離全部的頂點都是是無窮大的,除了源頂點自己。由於有5個頂點,所以全部的邊須要處理4次。路由

這裏寫圖片描述

按照如下的順序處理全部的邊:(B,E), (D,B), (B,D), (A,B), (A,C), (D,C), (B,C), (E,D).
第一次迭代獲得以下的結果(第一行爲初始化狀況,最後一行爲最終結果):

當 (B,E), (D,B), (B,D) 和 (A,B) 處理完後,獲得的是第二行的結果。
當 (A,C) 處理完後,獲得的是第三行的結果。
當 (D,C), (B,C) 和 (E,D) 處理完後,獲得第四行的結果。

這裏寫圖片描述

第一次迭代保證給全部最短路徑最多隻有1條邊。當全部的邊被第二次處理後,獲得以下的結果(最後一行爲最終結果):

這裏寫圖片描述

第二次迭代保證給全部最短路徑最多隻有2條邊。咱們還須要2次迭代(即所謂的鬆弛操做),就能夠獲得最終結果。

 

算法描述

1,.初始化:將除源點外的全部頂點的最短距離估計值 d[v] ——>+∞, d[s]——>0;
2.迭代求解:反覆對邊集E中的每條邊進行鬆弛操做,使得頂點集V中的每一個頂點v的最短距離估計值逐步逼近其最短距離;(運行|v|-1次)
3.檢驗負權迴路:判斷邊集E中的每一條邊的兩個端點是否收斂。若是存在未收斂的頂點,則算法返回false,代表問題無解;不然算法返回true,而且從源點可達的頂點v的最短距離保存在 d[v]中。

 

爲何要循環V-1次?
答:由於最短路徑確定是個簡單路徑,不可能包含迴路的,若是包含迴路,且迴路的權值和爲正的,那麼去掉這個迴路,能夠獲得更短的路徑若是迴路的權值是負的,那麼確定沒有解了.圖有n個點,又不能有迴路,因此最短路徑最多n-1邊。又由於每次循環,至少relax一邊因此最多n-1次就好了。

 

算法導論上的僞代碼:

BELLMAN-FORD(G, w, s)
1  INITIALIZE-SINGLE-SOURCE(G, s)
2  for i ← 1 to |V[G]| - 1
3       do for each edge (u, v) ∈ E[G]
4              do RELAX(u, v, w)
5  for each edge (u, v) ∈ E[G]
6       do if d[v] > d[u] + w(u, v)
7             then return FALSE
8  return TRUE
相關文章
相關標籤/搜索