zoukankan      html  css  js  c++  java
  • 图论SPFA

    复习笔记-SPFA求单源最短路

    一本通上的SPFA用的是邻接矩阵,而前向星的SPFA更为常用,所以作为巩固复习和改进,我写了这篇随笔。

    SPFA的基本操作

    基本原理

    动态逼近法。

    实现思路

    设立一个先进先出的队列用来保存待优化的结点,优化时每次取出队首结点u,并且用u点当前的最短路径估计值对离开u点所指向的结点v进行松弛操作,如果v点的最短路径估计值有所调整,且v点不在当前的队列中,就将v点放入队尾。这样不断从队列中取出结点来进行松弛操作,直至队列空为止。——度娘

    那么松弛操作是个啥玩意儿呢?

    如果IK + KJ < IJ

    那么IJ = IK + KJ

    也就是说,如果经过一个中转点到达终点比当前记录的两点最短路还要近,那么就把这个长度更新为两点最短路。

    伪代码

     1 SPFA(X){
     2     初始化:d[x][i]赋值为INF; d[x][x]=0;
     3     x入队;  更新visit;
     4     while(队里有元素){
     5         k = 队首; 队首出队; 
     6         while(i = 遍历以k为起点的所有边){
     7             取出 j = i;
     8             if(XK + KJ < XJ){
     9                 XJ = XK + KJ;
    10                 if(j不在队里,也就是!visit[j]){
    11                     j入队;
    12                     更新visit; 
    13                 }
    14             }
    15         } 
    16     } 
    17 }

    程序实现

    基本程序

    如果d[x][y]存储x到y的路长,断路存为INF,visit来表示一个点在不在队列内,那么我们可以这样实现SPFA

     1 void spfa(int x){
     2     d[x][x] = 0;
     3     queue <int> nod; nod.push(x); visit[x] = 1;
     4     while(nod.size()){
     5         int k = nod.front(); nod.pop(); visit[k] = 0;
     6         for(int j = 1; j <= n; j++){
     7             if(d[x][j] > d[x][k] + d[k][j]){
     8                 d[x][j] = d[x][k] + d[k][j];
     9                 if(!visit[j]){
    10                     nod.push(j);
    11                     visit[j]=1;
    12                 }
    13             }
    14         }
    15     }
    16 }

    与链式前向星的结合

    很明显上面的程序是针对用邻接矩阵存图的方式,那么如果我们使用链式前向星(如果不知道的话看这里

    用d[i]存储x到i的最短路长,初始化赋值为INF,d[x]赋值为0,visit[i]记录i是否在队列,那么程序是这样的(to为终点v为边权next为下一条边,head[i]为i为起点的第一条边)

     1 void spfa(int x){
     2     fill(d + 1, d + n + 1, INF); d[x] = 0;
     3     queue <int> nod; nod.push(x); visit[x] = 1;
     4     while(nod.size()){
     5         int k = nod.front(); nod.pop(); visit[k] = 0;
     6         for(int i = head[k]; i != 0; i = edge[i].next){
     7             int j = edge[i].to;
     8             if(d[j] > d[k] + edge[i].w){
     9                 d[j] = d[k] + edge[i].w;
    10                 if(!visit[j]){
    11                     nod.push(j);
    12                     visit[j]=1;
    13                 }
    14             }
    15         }
    16     }
    17 }

    这样就可以求出来x到每个点的最短路长了嘤。

    板子题

    LGOJ-P1339

    LGOJ-P2384

    LGOJ-P2299

    LGOJ-P1359

  • 相关阅读:
    CSAPP DataLab
    《计算机网络自顶向下》第二章应用层,笔记总结
    计算机网络自顶向下第二章套接字编程作业
    第二章---信息的表示与处理
    python界面使用gbk编码
    python修改获取xlsx数据
    刚安装了ftp之后无法使用root访问,服务器发回了不可路由的地址。使用服务器地址代替。
    ssh_exchange_identification: read: Connection reset
    <七>对于之前的一些遗漏的地方的补充
    (六)单例模式与多线程时的安全问题以及解决办法
  • 原文地址:https://www.cnblogs.com/Juruo1103/p/9966907.html
Copyright © 2011-2022 走看看