zoukankan      html  css  js  c++  java
  • 【笔记】最短路——SPFA算法

    ##算法功能

      找最短路(最长路?)

    ##算法思想

      用一个节点k更新节点i到节点j的最短路

    ##邻接链表存储

      基础而高效的图的存储方式

      存的是单向边(无向边可以看成两条有向边)

    ##实现

      维护节点i到源点s的最小值d[i]

      用队列实现

        维护队列z,

          用visit[]记录一个点是否在队列

        从源点开始进队列,每次弹出队头元素x,(标记visit[x]=0)

        用它的最短路d[x]将与它相连的节点y的最短路d[y]更新

        如果y不在队列(visit[y]==0),让y入队,记录(visit[y]=1)

        直到队列为空,所有节点的d[]都已维护好

    ##判断负环

      若图中存在负环,则更新时一定不断地让负环上的节点入队,负环上的点一定会无数次入队,最终死循环

      所以我们记录一个点入队的次数sum[],sum[i]在每次i入队时++,如果sum[i]贼大,贼大,证明有负环

        贼大到多大呢?贼大到2*m(m是边数)就肯定死循环了

        反正就是不能比2*m大(一共m条边,假设都与节点i相连,则i最多入队m次(当然不可能所有边都让i走一遍)(老师让sum[i]和m*2比较,不知道为啥那么大

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <cstdio>
     4 #include <string>
     5 #include <cstring>
     6 #include <cmath>
     7 #include <queue>
     8 #define N 100010
     9 #define M 100010
    10 //复杂度上限m*n
    11 //n个点,每个如m次 
    12 
    13 //正常nlogn
    14 
    15 //网格图贼慢 
    16 using namespace std;
    17 
    18 queue <int> z;
    19 int d[N],len,visit[N],n,m;
    20 
    21 //采用结构体存图 
    22 struct edge
    23 {
    24     int x,y,k,next;
    25 }a[M];
    26 // 邻接链表存储 
    27 int first[M];
    28 void ins(int x,int y,int k)
    29 {
    30     len++;
    31     a[len].x=x;
    32     a[len].y=y;
    33     a[len].k=k;
    34     a[len].next=first[x];
    35     first[x]=len;
    36 }
    37 int sum[N];
    38  
    39 int main()
    40 {
    41     cin>>n>>m;
    42     memset(d,63,sizeof(d));//63是billion(十亿)级别的10 6110 9567 
    43     int x,y,k;
    44     for(int i=1;i<=m;i++)
    45     {
    46         cin>>x>>y>>k;
    47         ins(x,y,k);
    48         ins(y,x,k);
    49     }
    50     int s;
    51     cin>>s;//源点 
    52     z.push(s);
    53     visit[s]=1;
    54     d[s]=0;
    55     
    56     //******主体代码 
    57     while(!z.empty())
    58     {
    59         x=z.front();
    60         for(int k=first[x];k;k=a[k].next)
    61         {
    62             y=a[k].y;
    63             if(d[x]+a[k].k < d[y])
    64             {    
    65                 d[y]=d[x]+a[k].k;
    66                 if(!visit[y])
    67                 {
    68 //                    sum[y]++;
    69                     z.push(y);//这是一个迭代的过程(老师说的,其实我不知道啥是迭代)
    70                     visit[y]=1;    
    71                 }
    72             }
    73         }
    74         z.pop();
    75         sum[x]++;
    76         /*if(sum[x] > 2*m)//判断负环 有时会用到 
    77         {
    78             printf("NO");
    79             break;
    80         }*/        
    81         visit[x]=0;
    82     }
    83     //********** 
    84     for(int i=1;i<=n;i++)    cout<<d[i]<<" ";//得到所有节点到源点的最短路 
    85     return 0;
    86 }
  • 相关阅读:
    python基础之集合
    python中关于赋值,深浅拷贝
    python小数据池
    python关于解构的例子
    test
    python字典的增,删,改,查
    python中元组常识,以及for 与 range 的用法!
    protobuf.js在长连接中前后台的交互使用方式
    vue-cli的浏览器兼容babel的配置
    前端处理在web打开app功能,有app就打开,没app就提示需要下载直接跳到下载app的页面
  • 原文地址:https://www.cnblogs.com/ZhengkunJia/p/12213249.html
Copyright © 2011-2022 走看看