spfa(shortest path faster algorithm)演算法與dijkstra演算法一樣都是尋找圖中兩點之間最短路徑的演算法。但是當圖中有負長度的路徑時,dijkstra演算法就不可以使用了,但是spfa演算法依舊可以在不出現負環的情況下使用。
spfa演算法因為與貝爾曼福德(bellman-ford)演算法比較相似,只是在它的演算法的基礎上進行了佇列優化。
把起始節點推入佇列,迴圈遍歷佇列。每次從隊頭取出乙個節點,如果可以通過該節點更新起始節點到其他節點最短距離的時候,我們就更新所有它能到達的子節點的距離,如果更新路徑的節點沒有在佇列中,就把它推入佇列,然後繼續遍歷佇列,直到隊列為空。這時我們就能得到起始節點到其他節點的最短路徑。
做出點邊關係的矩陣或其他資料模型這裡就不說了。假設起始節點為a。
幾乎所有的尋找最短路徑方法都是以做表,鬆弛兩個操作為主的。spfa演算法也是如此,首先我們需要乙個長度為節點數量n的陣列w表示起始節點到所有節點的最短路徑表。並把除了0位的其他位的值修改為乙個最大值。表示這時初始節點到它本身的距離位0,到其他節點的距離為無限大。
然後還需要乙個長度為節點數量n的陣列v表示相應節點是否在佇列中。(起始節點a開始時要入隊)
需要乙個佇列用於遍歷鬆弛節點之間的距離,並把其實節點入隊。
遍歷佇列,當佇列不為空時,隊頭出隊,判斷能否通過該節點縮短起始節點到其他節點的距離,達到鬆弛的目的。如果能,就更新距離,並且把更新了距離且不在不在佇列中的節點入隊。
第一次隊頭出隊
a節點出隊,然後判斷通過a節點是否能鬆弛起始節點到各節點的距離。這裡遍歷a節點的出路可知a有到b,c,d有出路,並且可以鬆弛起始節點到b,c,d的路徑,於是就更新陣列w的對應位置。並且節點b,c,d並不在佇列中,就把他們入隊。這時各個陣列和佇列如下圖。
第二次隊頭出隊
b節點出隊,遍歷b節點的出路可知b節點到f節點有出路且可以鬆弛最短路徑,於是更新最短路徑表w。f節點不在佇列中,所以f節點入隊,修改是否在佇列資訊表v,設定f節點的值為true。由於b節點出隊,設定b節點值為false。
第三次隊頭出隊
c節點出隊,c節點沒有出路,僅僅把它在陣列v的值改為false即可。
第四次隊頭出隊
d節點出隊,通過d節點,起始節點a到e節點和f節點的最短路徑可以得到更新,於是更新陣列w的e節點對應的值和f節點對應的值,並且把不存在於佇列的e節點入隊。
第五,六次隊頭出隊
由於佇列中剩下的節點f,e都沒有出路,於是他們出隊時僅僅修改陣列v中對應的值即可。這時隊列為空,迴圈遍歷停止。得到起始節點a到圖中各節點的最短路徑(陣列w)。
SPFA演算法的實現
本文通過一道oj題目來驗證下面超連結中有關spfa演算法的內容 spfa演算法原理 include includeusing namespace std vector pair graph 100010 int arrdis 100010 bool flag 100010 int n,m,s,t q...
Bellman Ford演算法,SPFA演算法
bellman ford 演算法能在更普遍的情況下 存在負權邊 解決單源點最短路徑問題。對於給定的帶權 有向或無向 圖g v,e 其源點為 s,加權函式w是 邊集e 的對映。對圖g執行 bellman ford 演算法的結果是乙個布林值,表明圖中是否存在著乙個從源點s 可達的負權迴路。若不存在這樣的...
Spfa演算法模版
const maxn 5000 type link node node record x,dis longint next link end var g array 1.maxn of link dist,q array 1.maxn of longint v array 1.maxn of boo...