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 }
  • 相关阅读:
    UVa 10118 记忆化搜索 Free Candies
    CodeForces 568B DP Symmetric and Transitive
    UVa 11695 树的直径 Flight Planning
    UVa 10934 DP Dropping water balloons
    CodeForces 543D 树形DP Road Improvement
    CodeForces 570E DP Pig and Palindromes
    HDU 5396 区间DP 数学 Expression
    HDU 5402 模拟 构造 Travelling Salesman Problem
    HDU 5399 数学 Too Simple
    CodeForces 567F DP Mausoleum
  • 原文地址:https://www.cnblogs.com/Mr94Kevin/p/9508376.html
Copyright © 2011-2022 走看看