zoukankan      html  css  js  c++  java
  • SPFA算法

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

     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 }
  • 相关阅读:
    2018级软件秋季总结
    对我影响最大的三位老师
    自我介绍
    Js中的一个日期处理格式化函数
    SQL update语句加减乘除运算
    用css让一个容器水平垂直
    position:absolute 的深入探讨
    java正则表达式
    Session
    使用Cookie进行会话管理
  • 原文地址:https://www.cnblogs.com/Mr94Kevin/p/9508376.html
Copyright © 2011-2022 走看看