SPFA單源最短路詳解

2021-07-15 13:13:40 字數 2880 閱讀 3889



適用範圍:給定的圖存在負權邊,這時類似dijkstra等演算法便沒有了用武之地,而bellman-ford演算法的複雜度又過高,spfa演算法便派上用場了。 我們約定有向加權圖g不存在負權迴路,即最短路徑一定存在。當然,我們可以在執行該演算法前做一次拓撲排序,以判斷是否存在負權迴路,但這不是我們討論的重點。

演算法思想:我們用陣列d記錄每個結點的最短路徑估計值,用鄰接表來儲存圖g。我們採取的方法是動態逼近法:設立乙個先進先出的佇列用來儲存待優化的結點,優化時每次取出隊首結點u,並且用u點當前的最短路徑估計值對離開u點所指向的結點v進行鬆弛操作,如果v點的最短路徑估計值有所調整,且v點不在當前的佇列中,就將v點放入隊尾。這樣不斷從佇列中取出結點來進行鬆弛操作,直至佇列空為止

期望的時間複雜度o(ke), 其中k為所有頂點進隊的平均次數,可以證明k一般小於等於2。

實現方法:

建立乙個佇列,初始時佇列裡只有起始點,再建立乙個**記錄起始點到所有點的最短路徑(該**的初始值要賦為極大值,該點到他本身的路徑賦為0)。然後執行鬆弛操作,用佇列裡有的點作為起始點去重新整理到所有點的最短路,如果重新整理成功且被重新整理點不在佇列中則把該點加入到佇列最後。重複執行直到隊列為空。

判斷有無負環:

如果某個點進入佇列的次數超過n次則存在負環(spfa無法處理帶負環的圖)

首先建立起始點a到其餘各點的

最短路徑**

首先源點a入隊,當佇列非空時:

1、隊首元素(a)出隊,對以a為起始點的所有邊的終點依次進行鬆弛操作(此處有b,c,d三個點),此時路徑**狀態為:

在鬆弛時三個點的最短路徑估值變小了,而這些點佇列中都沒有出現,這些點

需要入隊,此時,佇列中新入隊了三個結點b,c,d

隊首元素b點出隊,對以b為起始點的所有邊的終點依次進行鬆弛操作(此處只有e點),此時路徑**狀態為:

在最短路徑表中,e的最短路徑估值也變小了,e在佇列中不存在,因此e也要

入隊,此時佇列中的元素為c,d,e

隊首元素c點出隊,對以c為起始點的所有邊的終點依次進行鬆弛操作(此處有e,f兩個點),此時路徑**狀態為:

在最短路徑表中,e,f的最短路徑估值變小了,e在佇列中存在,f不存在。因此

e不用入隊了,f要入隊,此時佇列中的元素為d,e,f

隊首元素d點出隊,對以d為起始點的所有邊的終點依次進行鬆弛操作(此處只有g這個點),此時路徑**狀態為:

在最短路徑表中,g的最短路徑估值沒有變小(鬆弛不成功),沒有新結點入隊,佇列中元素為f,g

隊首元素f點出隊,對以f為起始點的所有邊的終點依次進行鬆弛操作(此處有d,e,g三個點),此時路徑**狀態為:

在最短路徑表中,e,g的最短路徑估值又變小,佇列中無e點,e入隊,佇列中存在g這個點,g不用入隊,此時佇列中元素為g,e

隊首元素g點出隊,對以g為起始點的所有邊的終點依次進行鬆弛操作(此處只有b點),此時路徑**狀態為:

在最短路徑表中,b的最短路徑估值又變小,佇列中無b點,b入隊,此時佇列中元素為e,b

隊首元素e點出隊,對以e為起始點的所有邊的終點依次進行鬆弛操作(此處只有g這個點),此時路徑**狀態為:

在最短路徑表中,g的最短路徑估值沒變化(鬆弛不成功),此時佇列中元素為b

隊首元素b點出隊,對以b為起始點的所有邊的終點依次進行鬆弛操作(此處只有e這個點),此時路徑**狀態為:

在最短路徑表中,e的最短路徑估值沒變化(鬆弛不成功),此時隊列為空了

最終a到g的最短路徑為14

#includeusing namespace std;

struct node

; node e[60000];

int visited[1505],dis[1505],st[1505],queue[1000];

int main()

for(int i=1;i<=m;i++)

start=1;

visited[start]=1;

dis[start]=0;

h=0;

r=1;

queue[r]=start;

while(h!=r)

{h=(h+1)%1000;

cur=queue[h];

int tmp=st[cur];

visited[cur]=0;

while(tmp!=-1)

{if (dis[e[tmp].x]

單源最短路徑 SPFA

給出乙個有向圖,請輸出從某一點出發到所有點的最短路徑長度。第一行包含三個整數n m s,分別表示點的個數 有向邊的個數 出發點的編號。接下來m行每行包含三個整數fi gi wi,分別表示第i條有向邊的出發點 目標點和長度。一行,包含n個用空格分隔的整數,其中第i個整數表示從點s出發到點i的最短路徑長...

單源最短路徑 SPFA演算法

求單源最短路徑的spfa演算法在bellman ford演算法的基礎上進行了改進,使其在能夠計算帶負權圖的單源最短路徑的基礎上,時間複雜度大幅度降低。時間複雜度 o k e k 2 基本演算法 設立乙個先進先出的佇列來儲存待優化的節點,優化時每次取出隊首節點u,並且用u點當前的最短路徑估計值對離開u...

Spfa單源最短路徑演算法

spfa 全稱shortest path faster algorithm,是求單源最短路徑的一種演算法.跟dijkstra類似,但是有一些不一樣。由於本人弱,不知道 有區別,請各位大神補充 我們來建乙個圖。首先,我們用e陣列表示各邊的關係,如下是初始狀態。我們開乙個dis陣列來儲存1號點到各點的最...