SPFA算法

Posted struct Edge

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SPFA算法相关的知识,希望对你有一定的参考价值。

 

SPFA算法

一.算法简介

SPFA(Shortest Path Faster Algorithm)算法是求单源最短路径的一种算法,它是Bellman-ford的队列优化,它是一种十分高效的最短路算法。

很多时候,给定的图存在负权边,这时类似Dijkstra等算法便没有了用武之地,而Bellman-Ford算法的复杂度又过高,SPFA算法便派上用场了。SPFA的复杂度大约是O(kE),k是每个点的平均进队次数(一般的,k是一个常数,在稀疏图中小于2)。

实现方法:建立一个队列,初始时队列里只有起始点,在建立一个表格记录起始点到所有点的最短路径(该表格的初始值要赋为极大值,该点到他本身的路径赋为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 }

 

 

 

 

(完)

 

以上是关于SPFA算法的主要内容,如果未能解决你的问题,请参考以下文章

SPFA算法以及负环判断模板

SPFA最短路算法

算法描述》关于SPFA和Dijkstra算法的两三事

题目1008:最短路径问题(SPFA算法)

最短路径——SPFA算法(C++)

hdoj2544 最短路(Dijkstra || Floyd || SPFA)