SPFA算法


 

SPFA算法

一.算法簡介

SPFA(Shortest Path Faster Algorithm)算法是求單源最短路徑的一種算法,它是Bellman-ford的隊列優化,它是一種十分高效的最短路算法。

很多時候,給定的圖存在負權邊,這時類似Dijkstra等算法便沒有了用武之地,而Bellman-Ford算法的復雜度又過高,SPFA算法便派上用場了。SPFA的復雜度大約是O(kE),k是每個點的平均進隊次數(一般的,k是一個常數,在稀疏圖中小於2)。

但是,SPFA算法穩定性較差,在稠密圖中SPFA算法時間復雜度會退化。

實現方法:建立一個隊列,初始時隊列里只有起始點,在建立一個表格記錄起始點到所有點的最短路徑(該表格的初始值要賦為極大值,該點到他本身的路徑賦為0)。然后執行松弛操作,用隊列里有的點去刷新起始點到所有點的最短路,如果刷新成功且被刷新點不在隊列中則把該點加入到隊列最后。重復執行直到隊列為空。

此外,SPFA算法還可以判斷圖中是否有負權環,即一個點入隊次數超過N。

 

二.算法圖解

給定一個有向圖,求A~E的最短路。

源點A首先入隊,並且AB松弛

擴展與A相連的邊,B,C 入隊並松弛。

B,C分別開始擴展,D入隊並松弛

D出隊,E入隊並松弛。

E出隊,此時隊列為空,源點到所有點的最短路已被找到,A->E的最短路即為8

以上就是SPFA算法的過程。

三.算法模板

 

 1 #include "bits/stdc++.h"
 2 
 3 using namespace std;
 4 const int maxN = 200010 ;
 5 struct Edge
 6 {
 7     int    to , next , w ;
 8 } e[ maxN ];
 9 
10 int    n,m,cnt,p[ maxN ],Dis[ maxN ];
11 int    In[maxN ];
12 bool    visited[ maxN ];
13 
14 void    Add_Edge ( const int x , const int y , const int z )
15 {
16     e[ ++cnt ] . to = y ;
17     e[ cnt ] . next = p[ x ]; 
18     e[ cnt ] . w = z ;
19     p[ x ] = cnt ;
20     return ;
21 }
22 
23 bool    Spfa(const int S)
24 {
25     int    i,t,temp;
26     queue<int>    Q;
27     memset ( visited , 0 , sizeof ( visited ) ) ; 
28     memset ( Dis , 0x3f , sizeof ( Dis ) ) ; 
29     memset ( In , 0 , sizeof ( In ) ) ;
30     
31     Q.push ( S ) ;
32     visited [ S ] = true ;
33     Dis [ S ] = 0 ;
34 
35     while( !Q.empty ( ) ) 
36     {
37         t = Q.front ( ) ;Q.pop ( ) ;visited [ t ] = false ;
38         for( i=p[t] ; i ; i = e[ i ].next )
39         {
40             temp = e[ i ].to ;
41             if( Dis[ temp ] > Dis[ t ] + e[ i ].w )
42             {
43                 Dis[ temp ] =Dis[ t ] + e[ i ].w ;
44                 if( !visited[ temp ] )
45                 {
46                     Q.push(temp);
47                     visited[temp]=true;
48                     if(++In[temp]>n)return false;
49                 }
50             }
51         }
52     }
53     return true;
54 }
55 
56 int main ( )
57 {
58     int    S , T ;
59 
60     scanf ( "%d%d%d%d" , &n , &m , &S , &T ) ;
61     for(int i=1 ; i<=m ; ++i )
62     {
63         int x , y , _ ;
64         scanf ( "%d%d%d" , &x , &y , &_ ) ;
65         Add_Edge ( x , y , _  ) ;
66     }
67 
68     if ( !Spfa ( S ) ) printf ( "FAIL!\n" ) ;
69     else               printf ( "%d\n" , Dis[ T ] ) ;
70 
71     return 0;
72 }

 

 

 

 

(完)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM