首页 > 编程语言 >【SPFA】最短路的一种算法

【SPFA】最短路的一种算法

时间:2024-01-13 17:37:25浏览次数:22  
标签:结点 松弛 短路 SPFA bellman ford 算法

  SPFA算法是在bellman-ford算法基础上优化而来,所以我们先讨论bellman-ford算法

bellman-ford算法的核心是‘松弛’。那么什么是松弛呢?以下图为例:

  假设数组d[i]表示源点s到达结点i的最短路径长度,那么松弛指的就是当d[a] + w < d[b],也就是说,这时候通过a到达b比原来的路径更短,此时,我们松弛d[b] = d[a] + w;

  bellman-ford算法核心思想简单,就是对m条边进行n-1次松弛操作,得到最短路径,如果还能松弛,说明存在负权环。如下所示

  

  如果一直绕着负环,那么负环上的结点的最短距离都是-INF。

  bellman-ford算法的伪代码如下

   

   我的代码:

 1 void bellman(){
 2     fill(d,d + maxn,INF);
 3     d[1] = 0;
 4     
 5     for(int i = 1; i <= n-1; i++){
 6         memcpy(backup,d,sizeof d);
 7         for(int j = 1; j <= m; j++){
 8             int v = edg[j].v;
 9             int u = edg[j].u;
10             int w = edg[j].w;
11             d[v] = min(d[v],backup[u] + w);
12         }
13     }
14 }

  backup数组是因为外层循环还有另一层含义,就是经过最多i条边,能完成的最短路径生成。

 

  注意到,一个结点被更新是由于它的起始结点被更新,那么,我们使用bfs优化,将被更新的结点储存下来,这里要注意,需要使用inq[]数组储存结点是否在队列中。

  以下是SPFA代码(非常像Dijkstr):

 1 bool SPFA(){
 2     memset(d,0x3f,sizeof d);
 3     queue<int> q;
 4     //1 q中元素都是被更新过的结点,为了防止重复更新结点,需要设置
 5     //cnt[i] 表示到达结点i最短路径经过的边数
 6     for(int i = 1; i <= n; i++){
 7         inq[i] = true;
 8         q.push(i);
 9     }
10     //这个for循环是有些题目是判断是否有负环,而不是是否有从1开始的负环,那么我们就将所有结点入队。
11     while(!q.empty()){
12         int u = q.front();
13         q.pop();
14         inq[u] = false;
15         
16         int len = G[u].size();
17         for(int i = 0; i < len; i++){
18             int v = G[u][i].first;
19             int w = G[u][i].second;
20             if(d[u] + w < d[v]){
21                 d[v] = d[u] + w;
22                 if(!inq[v]){
23                     q.push(v);
24                     cnt[v] = cnt[u] + 1;
25                     inq[v] = true;
26                     if(cnt[v] >= n) return false;
27                 }
28             }
29         }
30     }
31     
32     
33     return true;
34 }

  值得注意的是,cnt数组起到了和bellman-ford算法外循环类似的作用。一般来说,有负权边的问题都需要bellman-ford或者SPFA算法,但是正权边也可以先使用SPFA算法(虽然可能被卡,但是速度快)。

标签:结点,松弛,短路,SPFA,bellman,ford,算法
From: https://www.cnblogs.com/jiangjlon/p/17962639

相关文章

  • (坚持每天写算法)基础算法复习与学习part1基础算法1-7——高精度减法(处理t=1和t>1代码的
    题目:思路:这一道题其实和高精度加法的思路是差不多的,都是使用算式进行模拟。重点:关于代码怎么写,在高精度加法那里还看不太出来(我也没有写),但是在高精度减法这里就完全可以看出来了。我们在加法算式里面,一般是A[i]+B[i]+t,但是也可以这么写:t+A[i]+B[i],我们可以先写进位......
  • 文心一言 VS 讯飞星火 VS chatgpt (170)-- 算法导论13.2 3题
    三、用go语言,设在图13-2左边一棵树中,a、b和c分别为子树a、β和γ中的任意结点。当结点x左旋之后,a、b和c的深度会如何变化?文心一言:在二叉树中,左旋操作是改变节点的子节点顺序。原本的子节点β变为新的左子节点,原本的左子节点γ变为新的右子节点。对于给定的节点a、b和c,我们首......
  • 文心一言 VS 讯飞星火 VS chatgpt (168)-- 算法导论13.2 1题
    一、用go语言,写出RIGHT-ROTATE的伪代码。文心一言:在计算机科学中,右旋转(RIGHT-ROTATE)是一种常见的操作,通常用于数组或链表。以下是一个使用Go语言实现右旋转的伪代码:funcrightRotate(arr[]int,kint)[]int{n:=len(arr)k%=n//防止k大于n的情况rev......
  • 基于融合语义信息改进的内容推荐算法。Improved content recommendation algorithm in
    引言路漫漫其修远兮,吾将上下而求索。每天一篇论文,做更好的自己。本文读的这篇论文为发表于2023年5月28日的一篇名为《基于融合语义信息改进的内容推荐算法》(基于融合语义信息改进的内容推荐算法)的文章,文章主要介绍了基于内容的推荐技术在电子商务和教育领域的广泛应用,以及传统基......
  • 大数据分类算法深度解析
    博客:大数据分类算法深度解析1.背景大数据的快速增长带来了更多的机会和挑战。分类算法作为机器学习的基石之一,在处理大规模数据时变得尤为重要。其目标是根据已知的数据集,将新数据分配到预定义的类别中。2.特征提取与预处理在分类算法中,特征提取是非常关键的一步。特征是从原始数......
  • JVM7(GC 分代收集算法 VS 分区收集算法)
    1.分代收集算法当前主流VM垃圾收集都采用”分代收集”(GenerationalCollection)算法,这种算法会根据对象存活周期的不同将内存划分为几块,如JVM中的新生代、老年代、永久代,这样就可以根据各年代特点分别采用最适当的GC算法1.1.在新生代-复制算法每次垃圾收集都能发......
  • 秦九韶算法学习笔记
    快速求多项式——秦九韶算法计算\(\sum^n_i{a_i\timesx^i}\)的值。1.朴素算法算出每一项的值再相加,总共要进行\(\frac{n(n+1)}{2}\)次乘法,\(n\)次加法。2.秦九韶算法\(a_0+a_1x+a_2x^2+\dotsa_nx^n=(((a_nx+a_{n-1})x+a_{n-2}\dots)x+a_1)x......
  • [RFC6238] TOTP: 基于时间的一次性密码生成算法
    原创 给我馍馍 给我馍馍 2019-03-2822:42在闲暇时间做了一个TOTP相关的开源项目,在项目初步完成之余,我尝试对[RFC6238]文档进行了翻译,供大家参考与查阅,若有不妥之处,还望各位前辈海涵斧正。 生活中我们会经常使用到TOTP的算法应用,如银行的动态口令器、网络游戏中的将军令、......
  • 文心一言 VS 讯飞星火 VS chatgpt (177)-- 算法导论13.3 6题
    六、用go语言,说明如果红黑树的表示中不提供父指针,应当如何有效地实现RB-INSERT。文心一言:红黑树是一种自平衡的二叉搜索树,其中每个节点都包含一个颜色属性(红色或黑色),并且满足以下性质:节点是红色或黑色。根节点是黑色。所有叶子节点(NIL或空节点)都是黑色。如果一个节点是红色的,则......
  • 【教3妹学编程-算法题】统计出现过一次的公共字符串
    3妹:哈哈哈哈哈哈,太搞笑了~呵呵呵呵呵呵2哥:3妹干嘛呢,笑的这么魔性!3妹:在看王牌对王牌,老搞笑了2哥:这季好像没有贾玲吧。3妹:是啊,听说贾玲去导电影了,还狂瘦了100斤呢,哎,我也该减减肥了。2哥:切,你每隔几天就会说要减肥,也没见你减啊3妹:不吃饱哪有力气减肥,我每天还要刷题、找工作,多辛苦啊......