spfa
是bellman-ford的佇列優化,時效性相對好,時間複雜度o(ke)。
與bellman-ford演算法類似,spfa演算法採用一系列的鬆弛操作以得到從某乙個節點出發到達圖中其它所有節點的最短路徑。所不同的是,spfa演算法通過維護乙個佇列,使得乙個節點的當前最短路徑被更新之後沒有必要立刻去更新其他的節點,從而大大減少了重複的操作次數。
spfa演算法可以用於存在負數邊權的圖,這與dijkstra演算法是不同的。
與dijkstra演算法與bellman-ford演算法都不同,spfa的演算法時間效率是不穩定的,即它對於不同的圖所需要的時間有很大的差別。
在最好情形下,每乙個節點都只入隊一次,則演算法實際上變為廣度優先遍歷,其時間複雜度僅為o(e)。另一方面,存在這樣的例子,使得每乙個節點都被入隊(v-1)次,此時演算法退化為bellman-ford演算法,其時間複雜度為o(ve)。
spfa演算法在負邊權圖上可以完全取代bellman-ford演算法,另外在稀疏圖中也表現良好。但是在非負邊權圖中,為了避免最壞情況的出現,通常使用效率更加穩定的dijkstra演算法,以及它的使用堆優化的版本。通常的spfa
很多時候,給定的圖存在負權邊,這時類似dijkstra等演算法便沒有了用武之地,而bellman-ford演算法的複雜度又過高,spfa演算法便派上用場了。spfa的複雜度大約是o(ke),k是每個點的平均進隊次數(一般的,k是乙個常數,在稀疏圖中小於2)。
實現方法:建立乙個佇列,初始時佇列裡只有起始點,在建立乙個**記錄起始點到所有點的最短路徑(該**的初始值要賦為極大值,該點到他本身的路徑賦為0)。然後執行鬆弛操作,用佇列裡有的點去重新整理起始點到所有點的最短路,如果重新整理成功且被重新整理點不在佇列中則把該點加入到佇列最後。重複執行直到隊列為空。
此外,spfa演算法還可以判斷圖中是否有負權環,即乙個點入隊次數超過n。
具體用鄰接表怎麼儲存,看關於 bellman演算法的介紹。
#include
#include
struct node;
struct shuzhu;
void initialize_source(struct shuzhu*a,int n);
void spfa(struct shuzhu* a,int n);
int main()
/* //檢驗儲存**的正確性
for(i=1;i<=m;i++)
printf("\n");}*/
//spfa演算法,計算 1號點到其他點的最短路
spfa(a,n);
//列印結果
for(i=2;i<=n;i++)
return0;}
void initialize_source(struct shuzhu* a,int n)
return;
}void spfa(struct shuzhu* a,int n)
; q[0]=1;
j=j+1;
while(i+1 != j)//隊列為空
q=q->p;}}
return;
}
最短路演算法 SPFA
單源最短路徑,不可以處理含負權邊的圖但可以用來判斷是否存在負權迴路 複雜度o ke k 2,e 為邊數 bellman ford 演算法的優化,實質與前演算法一樣,但優化的關鍵之處在於 只有那些前面被鬆弛過的點才有可能去鬆弛它們的鄰接點。include include include include...
最短路 spfa演算法
板子補完計畫絕讚繼續中 這篇部落格就來寫一寫spfa 這我居然板子都打錯了一次,我太弱啦!先來看一下定義 引自 首先說明,spfa是一種單源最短路徑演算法,所以以下所說的 某點的最短路徑長度 指的是 某點到源點的最短路徑長度 我們記源點為s,由源點到達點i的 當前最短路徑 為d i 開始時將所有d ...
最短路徑演算法 SPFA
求最短路徑的演算法有許多種,除了排序外,恐怕是oi界中解決同一類問題演算法最多的了。最熟悉的無疑是dijkstra,接著是bellman ford,它們都可以求出由乙個源點向其他各點的最短路徑 如果我們想要求出每一對頂點之間的最短路徑的話,還可以用floyd warshall。spfa是這篇日誌要寫...