码迷,mamicode.com
首页 > 编程语言 > 详细

SPFA算法

时间:2018-08-20 23:49:56      阅读:342      评论:0      收藏:0      [点我收藏+]

标签:最短路算法   amp   printf   算法复杂度   取出   负环   pac   出队   jks   

 1 #include<cstdio>
 2 #include<cctype>
 3 #include<cstring>
 4 #include<queue>
 5 using namespace std;
 6 const int inf=0x3f3f3f3f;
 7 int n,m,s,head[maxn],eid,d[maxn],inq[maxn],cnt[maxn];
 8 struct edge {
 9     int v,w,next;
10     edge(int v=0,int w=-1):v(v),w(w) {}
11 } E[maxm];
12 void init() { //还是不要忘记初始化!
13     memset(head,-1,sizeof(head));
14     memset(d,inf,sizeof(d));
15 }
16 void insert(int u,int v,int w) {
17     E[eid]=edge(v,w);
18     E[eid].next=head[u];
19     head[u]=eid++;
20 } //邻接表存储,时间和空间上都会提高效率
21 queue<int> q;
22 bool spfa() {
23     d[s]=0;
24     q.push(s); //初始先将源点入队
25     inq[s]=1;
26     while(!q.empty()) {
27         int u=q.front();
28         q.pop();
29         inq[u]=0;
30         for(int p=head[u];p+1;p=E[p].next) {
31             int v=E[p].v;
32             if(d[v]>d[u]+E[p].w) { //松弛
33                 d[v]=d[u]+E[p].w;
34                 if(++cnt[v]>=n) return false; //如果一个点被更新超过n-1次
35                 //说明存在负环,不存在最短路
36                 if(!inq[v]) { //结点不在队列中就可以入队
37                     q.push(v); //同一结点可能会多次入队
38                     inq[v]=1; //但不会同时出现在队列中
39                 }
40             }
41         }
42     }
43     return true;
44 }
45 int main() {
46     scanf("%d%d%d",&n,&m,&s);
47     init();
48     int u,v,w;
49     for(int i=1;i<=m;++i) {
50         scanf("%d%d%d",&u,&v,&w);
51         insert(u,v,w);
52     }
53     spfa();
54     for(int i=1;i<=n;++i) {
55         if(i!=1) putchar( );
56         printf("%d",d[i]);
57     }
58     return 0;
59 }

 

SPFA是一种单源最短路算法,与Dijkstra不同的是,他可以处理负边权,而且能判断负环。SPFA是Bellman算法的队列优化,在过程上和BFS有些类似。SPFA的算法流程大时这样的,先将源点加入队列中,只要队列不为空,取出队首元素,用他去更新与他相连的点的最短路,若成功更新且被更新的点不在队列当中,就将他加入队列。由于每个结点最多被取出n-1次(n为结点总数),因此可以记录结点被取出的次数,若超过n-1次,说明图中存在负环,不存在最短路。SPFA的算法复杂度很玄,可以构造数据故意卡掉SPFA,有兴趣可以自行了解一下,在边权为正的情况下,最好选择堆优化的Dijkstra。SPFA还有两种优化,SLF和LLL,不过还是可以卡掉,而且算法竞赛一般用不到。

 

SPFA算法

标签:最短路算法   amp   printf   算法复杂度   取出   负环   pac   出队   jks   

原文地址:https://www.cnblogs.com/Mr94Kevin/p/9508376.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!