spfa演算法(shortest path faster algorithm),是經佇列優化的單源最短路bellman-ford演算法通常用於求含負權邊的單源最短路徑,以及判負權環。spfa演算法最壞情況下複雜度和樸素的bellman-ford演算法相同,為o(ve),一般情況為o(ke),其中k為常數,由圖的邊權分布決定,所以複雜度不是很穩定,如若必須要避免最壞情況的出現,通常使用效率更加穩定的dijkstra演算法。
從bellman-ford演算法中我們得知,如果乙個點上次沒有被鬆弛過,那麼下次就不會從這個點開始鬆弛,而每一遍鬆弛只是從源點出發樹狀地一層一層擴張,所以每一遍去試著鬆弛全部的邊實在是太浪費時間,因此spfa的思路是:將上一次鬆弛過的點放入佇列,只鬆弛與佇列中的點有關的邊,就可以忽略掉那些不可被鬆弛的邊,而且利用佇列迴圈鬆弛,動態逼近路徑的最優解,即最短路。
具體過程描述:dis陣列全部初始化為inf,vis陣列全部初始化為false,源點s,dis[s] = 0,將s放入佇列,vis[s] = true,開始類似bfs的迴圈過程:隊首出隊,vis[隊首] = false(這裡跟bfs不同,因為當前隊首的dis值可能不是最優解,有可能要再次入隊),將其與其子點之間的邊分別試著鬆弛,可鬆弛的話若子點vis為false,vis[子點] = true,子點入隊。不斷迴圈該過程,直至隊空。
這就相當於從源點開始,樹狀地層層更新其子點的dis值,因圖是錯綜複雜的,所以所以點都有可能會被多次更新,那麼當他們的dis值為正確的最短路值時便不再被更新,也不被看做子點,基於此,當找不到子點時,演算法就結束了,所有點的dis值均已被更新為正確的最短路值。
原始spfa**:
鏈式前向星:
void spfa(int s)}}
}}
鄰接矩陣:
void spfa(int s)}}
}}
spfa演算法有兩種優化方式:slf和lll
slf:small label first 策略,設要加入的節點是j,隊首元素為i,若dist(j) < dist(i)則將j插入隊首,否則插入隊尾。
lll:large label last 策略,設隊首元素為i,佇列中所有dist值的平均值為x,若dist(i)>x則將i插入到隊尾,查詢下一元素,直到找到某一i使得dist(i)<=x,則將i出對進行鬆弛操作。
兩者都一般可提速15%~20%,slf+lll甚至最高可提速50%,可隨情況優化使用。
SPFA演算法及其應用和優化
spfa演算法及其應用和優化 by mps 問題引入 又是一年春運時,因為睡懶覺而導致搶不到票的你,只能打車回家了,而無疑會消耗許多錢財 黑車.為了盡可能的節省錢,你希望走的是最短路,路途中會經過n個城市,而你每次經過兩個城市之間的高速公路時,都會損耗ci元,假設其中包含了所有的價錢 郵費,過橋費之...
貝爾曼 福特最短路演算法及其優化(SPFA)
日常膜拜dalao 財神萬歲!日常凌晨水題解。我發誓這是我今天最後一篇部落格了。話說,我的部落格一般解釋全在 注釋裡面,而且講的不細緻。真的想詳細看模擬的話參見dalao的部落格 為什麼我們不用dijkstra演算法?因為,dijkstra無法處理負權邊的狀況 這個我這篇部落格不細講 而貝爾曼 福特...
SPFA及其優化 他復活了
spfa算是一種比較萬能的最短路演算法了 時間複雜度 o mn 特點 1.每個點可以入隊多次 2.不能處理負環,但可以判斷負環 3.佇列優化減少一些冗餘的鬆弛操作 貼乙個模板題 include include include include include include includeusing ...