• 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 }
  • 相关阅读:
    Hadoop学习笔记—12.MapReduce中的常见算法
    Hadoop学习笔记—11.MapReduce中的排序和分组
    Hadoop学习笔记—10.Shuffle过程那点事儿
    Hadoop学习笔记—9.Partitioner与自定义Partitioner
    Hadoop学习笔记—8.Combiner与自定义Combiner
    Hadoop学习笔记—7.计数器与自定义计数器
    Hadoop学习笔记—6.Hadoop Eclipse插件的使用
    Hadoop学习笔记—5.自定义类型处理手机上网日志
    Hadoop学习笔记—4.初识MapReduce
    Hadoop学习笔记—3.Hadoop RPC机制的使用
  • 原文地址:https://www.cnblogs.com/Mr94Kevin/p/9508376.html
Copyright © 2020-2023  润新知