1、算法概述算法
Bellman-Ford算法解決的是通常狀況下的單源最短路徑問題。所謂單源最短路徑問題:給定一個圖G=(V,E),咱們但願找到從給定源結點s屬於V到每一個結點v屬於V的最短路徑。單源最短路徑問題能夠用來解決許多其餘問題,其中包括下面幾個最短路徑的變體問題。包括單目的最短路徑問題、單結點最短路徑問題、全部結點對最短路徑問題,這裏不詳細介紹。回到bellman-Ford,在這裏,邊的權重能夠爲負值。給定帶權重的有向圖G=(V,E)和權重函數W : E-->R,Bellman-Ford算法返回一個布爾值,以代表是否存在一個從源點能夠到達的權重爲負值的環路。若是存在這樣的環路,算法將告訴咱們不存在解決方案。若是沒有這種環路存在,算法將給出最短路徑和它們的權重。邊的權值能夠爲負數、實現簡單,缺點是時間複雜度太高,高達O(VE)。但算法能夠進行若干種優化,提升了效率。函數
天然語言描述測試
對有向圖,用貝爾曼-福特算法求以爲源點的最短路徑的過程:優化
僞代碼表示
spa
BellmanFord(G,s) for i = 0 to n-1 do dist[i]= ∞ Pred[i]= 0 dist[s]=0 for k = 1 to n-1 do foreach ∈ do if do foreach ∈ do if do return "No Shortest Path" return dist[]
2、原理htm
爲何說最短路徑不存在負環呢?隊列
若是圖G包含從s能夠達到的權重爲負值的環路,則最短路徑權重無定義。從s到該環路上的任意結點的路徑都不多是最短路徑,由於咱們只要沿着任何「最短」路徑再遍歷一次權重爲負值的環路,則老是能夠找到一條權重更小的路徑。若是從結點s到結點v的某條路徑上存在權重爲負值的環路,咱們定義s到v的最短路徑等於負無窮。
ip
鬆弛操做get
它的原理是對圖進行V-1次鬆弛操做,獲得全部可能的最短路徑。對於一條邊(u,v)的鬆弛過程爲:首先測試一下是否能夠對源點s到v的最短路徑進行改善。測試的方法是,將從結點s到結點u之間的最短路徑距離加上結點u與v之間的權重,並與當前的s到v的最短路徑估計進行比較,若是前者更小,則對v.d(源點s到v的最短路徑) 和v.π(前驅結點)進行更新。
it
每次鬆弛操做其實是對相鄰節點的訪問,第次鬆弛操做保證了全部深度爲n的路徑最短。因爲圖的最短路徑最長不會通過超過條邊,因此可知貝爾曼-福特算法所得爲最短路徑。
負邊權操做
與迪科斯徹算法不一樣的是,迪科斯徹算法的基本操做「拓展」是在深度上尋路,用於有向無環圖的最短路徑算法對每條邊僅鬆弛一次。Bellman-Ford「鬆弛」操做則是在廣度上尋路,這就肯定了貝爾曼-福特算法能夠對負邊進行操做而不會影響結果。
負權環斷定
由於負權環能夠無限制的下降總花費,因此若是發現第次操做仍可下降花銷,就必定存在負權環。
3、隊列優化——SPFA
求單源最短路的SPFA算法的全稱是:Shortest Path Faster Algorithm。鬆弛操做一定只會發生在最短路徑前導節點鬆弛成功過的節點上,用一個隊列記錄鬆弛過的節點,能夠避免了冗餘計算。複雜度能夠下降到O(kE),k是個比較小的係數(而且在絕大多數的圖中,k<=2,然而在一些精心構造的圖中可能會上升到很高)