最短路径算法----Bellman-ford和SPFA算法

最短路径算法总结(Dijkstra、Bellman-ford、SPFA和Floyd) 在最短路径算法中,常用的有Dijkstra、Bellman-ford、spfa、Floyd这四大算法 Dijkstra:迪克斯特拉算法 Bellman-ford:贝尔曼-福特算法 SPFA:Shortest Path Faster Algorithm算法 Floyd:弗洛伊德算法 四大算法介绍 简介 Dijkstra:是一种用于求解单源最短路径的贪心算法。它从起始节点开始,逐步扩展到其他节点,每次选择当前距离起始节点最近的节点进行扩展。通过不断更新节点的最短距离,最终得到起始节点到其他所有节点的最短路 阅读详情

思路类似Dijkstra,可以处理负权边,还可以发现负权回路。

核心也是:对于边e(i,j), 如果w(i) + e(i,j) < w(j),就更新w(j)。这是一个松弛操作,即:估计的最短路径值渐渐地被更加准确的值替代,直至得到最优解(wiki)

对于图

有

def bellman_ford(graph, start_node):
	# graph:n*n matrix
	# find min distance from start_node
	length = len(graph)
	s = {start_node:0}          # the minimum distance between node i and v

	# init s: O(Vertex)
	for node in xrange(0, length):
		if node == start_node:
			continue
		s[node] = max_int

	# loose
	# run (vertex - 1) times
	for v in xrange(1, length):
		# for every edge
		for i in xrange(0, length):
			for j in xrange(0, length):
				if graph[i][j] != max_int and s[i] + graph[i][j] < s[j]:
					s[j] = s[i] + graph[i][j]

	return s

使用二维矩阵表示图,时间复杂度是O(Vertex^3);

如果使用图数据结构,可以达到O(Vertex * Edge)

由于存在负权回路,还有一步检查的操作:

def test_negate_circle(graph, s):
	# for every edge
	length = len(graph)
	for i in xrange(0, length):
		for j in xrange(0, length):
			if graph[i][j] != max_int and s[i] + graph[i][j] < s[j]:
				return True
	return False

如果有负值回路,就说明永远能找到到目标点更小的一条边。


为什么需要遍历Vertex-1遍呢?我认为和遍历图的所有节点的深度有关:


对于上面的第一张图,深度为1,显然只需要遍历一次边就能得到结果了。但是对于第二张图,在最坏的情况下,需要遍历3次才可以。

下面假设所有边的权值为1,人肉模拟一下最坏结果:

第一遍:u:{0:0, 1:1, 2:max_int, 3:max_int}

第二遍:u:{0:0, 1:1, 2:2, 3:max_int}

第三遍:u:{0:0, 1:1, 2:2, 3:3}


所以,遍历Vertex-1次可以改为:遍历所有边的最大深度。

什么是遍历所有边的最大深度?



从上图来看,如果用BFS遍历所有点得到图的深度为2:

第零层:0

第一层:1,2

第二层:3

但是实际上,可能存在0->1->2->3,使得0~3的距离最短。

遍历所有边的最大深度的结果则是:

第零层:0

第一层:1[e(0,1)],2[e(0,2)]

第二层:2[e(1,2)]

第三层:3[e(2,3)]


这个层数只是估算出来的最坏情况,也就是循环次数的上界

实际上,如果在一次遍历所有的边的时候,没有松弛操作,那么继续遍历也没有意义了。

这就是SPFA的思想:松弛操作必定只会发生在最短路径前导节点松弛成功过的节点上,用一个队列记录松弛过的节点,可以避免了冗余计算。

也就是说,只有对更新过的w(i),才有可能出现w(i) + e(i,j) < w(j)。第一个更新的就是开始节点啦,更新后的权重为0。

def SPFA(graph, start_node):
	length = len(graph)
	s = {i:max_int for i in xrange(0, length)}
	s[start_node] = 0
	queue_loose = deque([start_node])
	circle_tester = defaultdict(lambda : 0)

	while queue_loose:
		i = queue_loose.popleft()
		# update s
		for j in xrange(0, length):
			if graph[i][j] != max_int and s[i] + graph[i][j] < s[j]:
				s[j] = s[i] + graph[i][j]
				queue_loose.append(j)

				# test circle
				circle_tester[j] += 1
				if circle_tester[j] == length:
					# has negate circle
					return None
	return s

负权环的检测我也写在SPFA里面了,如果一个节点访问次数大于Vertex次,就认为有环。

原因我猜想是:最多有Vextex-1个节点(除去自己)会对某个节点产生影响,如果大于这个数,说明有负环。

如果不对,希望大家提出指正~谢谢


驱动

graph = [[0, 7, 9,  max_int,  max_int, 14],
         [7, 0, 10, 15, max_int, max_int],
         [9, 10, 0, 11, max_int, 2],
         [max_int, 15, 11, 0, 6, max_int],
         [max_int, max_int,  max_int,  6, 0, 9],
         [14, max_int,  2,  max_int, 9, 0]]
print SPFA(graph, 0)



最短路径(Dijkstra、Bellman-Ford和SPFA算法) 最短路径(Dijkstra、Bellman-Ford和SPFA算法) 前言 图的存储方式 邻接矩阵 邻接表 链表建立 利用vector 结构体 核心思路 Dijkstra算法 图解 基本思想 求解步骤 细节解释 变量的意义 初始化 迭代次数 更新条件 完整代码 Bellman-Ford算法 思路: 变量说明 初始化 完整代码 Bellman-Ford 检测图是否含有负圈(回路) 思路 代码 Bellman-Ford 算法优化 SPFA算法 思路 完整代码 算法的比较 阅读详情

相关推荐

Dijkstra、Bellman_Ford、SPFA、Floyd算法复杂度比较

Dijkstra:适用于权值为非负的图的单源最短路径,用斐波那契堆的复杂度O(E+VlgV) BellmanFord:适用于权值有负值的图的单源最短路径,并且能够检测负圈,复杂度O(VE) SPFA:适用于权值有负值,且没有负圈的图的单源最短路径,论文中的复杂度O(kE),k为每个节点进入Queue的次数,且k一般但此处的复杂度证明是有问题的,其实SPFA的最坏情况应该是O(VE). Flo

xiazdong 4万+

SPFA算法(最短路径算法)

SPFA-图论-最小路径

m0_64045085的博客 2万+

中国IP发展之面面观

谢学军/邱善勤2006-1-25 9:29:28电子经理世界       IP远没有我们当初想象的那么简单   当SoC设计方法学刚刚传到国内的时候,学界为之欢呼雀跃,由于IP/SoC设计技术的使用,可以将发达国家用几年甚至十几年积累起来的设计技术直接为我所用,使中国的集成电路跳过漫长的积累阶段,迅速站到较高的起点上。因此在当时看来,IP/SoC设计技术是我国提升设计水平、发展

klxdmm305的专栏 1188

搜索与图论 - spfa 算法

spfa 算法

每天进步一点点! 6259

R语言vegan包实战:用varpart函数搞定生态学VPA分析(附完整代码与数据集)

本文详细介绍了如何使用R语言vegan包中的varpart函数进行生态学方差分解分析(VPA),包括数据准备、模型构建、结果解读和可视化呈现。通过完整的代码示例和数据集,帮助研究者理解不同环境因子对生物群落变化的相对贡献,并掌握显著性检验等高级技巧。

weixin_42525005的博客 450

Vienna整流器SVPWM调制:7扇区划分与中点电位平衡的MATLAB/Simulink实现解析

本文深入解析Vienna整流器的SVPWM调制技术,重点介绍7扇区划分与中点电位平衡的MATLAB/Simulink实现方法。通过详细的算法推导和仿真模型构建,帮助工程师掌握整流器闭环控制策略,优化功率转换效率。内容涵盖扇区判断逻辑、矢量作用时间计算及中点电位平衡的PID调节等核心技术要点。

weixin_33937499的博客 387

SPFA 算法总结

回顾一下使用邻接表的 SPFA 的算法 如上图所示: 假设原点是 1 ,也就是说 1 在队列中 将与 1 节点连接的节点放入队列中 此时更新 d[2]=3 , d[3]=9 , d[4]=7 , d[5]=3 将以上节点放入队列中 此时队列里有 2,3,4,5 节点 然后 2 出队,发现与 2 连接的有 3 号节点,更新 d[3]=5, 但是 3 节点在队列中,所以不再进行操作 之后 3 号节点出队,与 3 号节点连接的只有 4 号节点,但此时 d[4]=7<9+4,选择不跟新..

C_Dreamy的博客 5433

EB tresos配置指南:CAN通信信号收发全流程解析

本文详细解析了使用EB tresos配置工具实现AUTOSAR架构下CAN通信信号收发功能的全流程。从环境准备、COM模块信号定义、PduR路由配置、CanIf硬件抽象到CAN驱动层设置,提供了清晰的步骤指南和关键配置要点,帮助开发者快速打通从应用层到物理层的数据链路,实现可靠的CAN通信。

weixin_29192141的博客 509

【智能算法】SPFA算法

SPFA算法,全称Shortest Path Faster Algorithm,是Bellman-Ford算法的一种队列优化形式,由西南交通大学段凡丁于1994年提出(尽管其证明存在错误,且队列优化的概念在Bellman-Ford算法提出后不久即已存在)。SPFA算法主要用于求解含有负权边的单源最短路径问题,并具备判断负权环的能力。

大雨淅淅的博客 2538

K-means算法代码实现(python)

K-means算法代码实现以及解决质心选择问题 计算距离 距离通常使用欧几里得距离来衡量 def euclDistance(vector1, vector2): return np.sqrt(sum((vector2 - vector1) ** 2)) 初始化质心 def initCentroids(data, k): numSamples, dim = data.shape ...

江南小帅瓜的博客 1万+

Axure RP9汉化+授权全攻略:从下载到激活一步到位(附最新授权码)

本文提供Axure RP9从下载安装到界面汉化的完整指南,帮助设计师和产品经理快速上手这款原型设计工具。详细讲解了如何安全获取软件、执行汉化操作、理解核心界面布局,并介绍了创建交互原型和生成HTML文件的基础步骤,助力用户高效开展设计工作。

cuda7parallel的博客 1144

SPFA算法详解

前置知识:Bellman-Ford算法 前排提示:SPFA算法非常容易被卡出翔。所以如果不是图中有负权边,尽量使用Dijkstra!(Dijkstra算法不能能处理负权边,但SPFA能) 前排提示*2:一定要先学Bellman-Ford! 0.引子 在Bellman-Ford算法中,每条边都要松弛\(n-1\)轮,还不一定能松弛成功,这实在是太浪费了。能不能想办法改进呢? 非常幸运,SPFA算法...

qq_14886903的博客 6299

5、硬件工程师笔试面试——上拉电阻、下拉电阻(2025版本)

本文系统介绍了上拉电阻和下拉电阻的原理与应用。上拉电阻通过连接电源确保电路高电平状态,常用于数字电路防抖、OC门驱动等场景;下拉电阻连接地线维持低电平,适用于低电平触发电路。文章详细分析了两种电阻的选择方法、功耗与响应速度的平衡策略,以及在高速信号传输中的影响差异。同时对比了二者的优缺点,并提供了模拟电路中的应用实例。最后给出了电阻值计算的工程方法,为硬件工程师的电路设计提供了实用参考。

XU157303764的博客 2870

图论算法之最短路径(Dijkstra、Floyd、Bellman-ford和SPFA)

图论算法之最短路径(Dijkstra、Floyd、Bellman-ford和SPFA) 1、图论最短路径概述 图论算法为了求解一个顶点到另一个顶点的最短路径,即如果从图中某一顶点(称为源点)到达另一顶点(称为终点)的路径可能不止一条,如何找到一条路径,使得沿此路径各边上的权值总和(即从源点到终点的距离)达到最小,这条路径称为最短路径(shortestpath)。 最短路径有很多特殊的情况,包括有向图还是无向图,有没有负权边等。通常解决图论中最短路径问题的算法有Dijkstra、Floyd、Bellman-f

HX_2021 1万+

如何通过 GitHub Actions 使用 SSH 自动化部署到阿里云 ECS 实例

通过 GitHub Actions 和 SSH 自动化部署,可以显著提高你的开发效率和部署的可靠性。本文介绍了如何生成 SSH 密钥、将公钥添加到阿里云 ECS 实例、将私钥添加到 GitHub Secrets,以及编写 GitHub Actions 工作流来实现自动化部署。希望这篇文章对你有所帮助!

吃面不喝汤的博客 1511

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

最短路径Bellman-Ford算法和SPFA算法详解

最短路径Bellman-Ford算法和SPFA算法详解

m0_72674633的博客 1686

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

单源最短路径:bellman-ford算法和SPFA算法

前面讲了单源最短路径的Dijkstra算法和任意两点间最短路径的Floyd算法,今天我们来看一下求单源最短路径的另外两种常用的算法:bellman-ford算法和SPFA算法。至于为什么要把这两个放在一起呢,比较SPFA算法是对bellman-ford算法的改进和优化。         我们先来看一下bellman-ford算法:其实bellman-ford算法和Dijkstra算法是有相似之处

AC_Gibson的专栏 1169

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

最短路径问题:Dijkstra算法、Floyd算法、Bellman-Ford算法和SPFA算法

最短路径问题就是在网络中,让我们求两个不同顶点之间的所有路径中,边的权值之和最小的那一条路径,对于不同种类的图和我们我们分为以下几种情况: (1)单源最短路径: 从固定源点出发,求其到所有其他顶点的最短路径。 (2)多源最短路径: 任意两顶点间的最短路径。 (3)无权图的最短路径: 就是经过边个数最少(也是经过顶点数最少的)的路径,边的个数(顶点数-1)即为最短路径长度。 (4)有权图的最短路径:...

derbi123123的博客 454

单源最短路径__SPFA和Bellman−Ford算法

题目 这些算法和差分约束算法是什么关系 Bellman−Ford算法 Bellman−Ford算法精讲 题目的背景是不等式,但是可以转化成求起点到终点的最短路径。 对于有n个点,m条边的图,福特算法的复杂度是(n-1)*m,即每趟内循环张弛边数m次,最坏的情况张弛n-1次,最好的情况张弛1次。取n-1次。 是对边进行张弛操作。dis[e[i].to] > dis[e[i].from] + e[i].w就需要张弛了。 原题给的是x1-x2<= 3,转化成 x1<= x2+3,就长得很像d

qq_45895217的博客 151

【最短路径】:Dijkstra算法、SPFA算法、Bellman-Ford算法和Floyd-Warshall算法

求最短路径最常用的算法有: Dijkstra算法、SPFA算法、Bellman-Ford算法和Floyd-Warshall算法。 Dijkstra算法、SPFA算法、Bellman-Ford算法这三个求单源最短路径,最后一个Floyd-Warshall算法可以求多源最短路径也可以求单源路径,效率比较低。 SPFA算法是Bellman算法的队列优化。 Dijkstra算法不能求带负权边的最短

柳婼 の blog 3591

最短路径SPFA和Bellman-Ford算法

参考模板: #include<bits/stdc++.h> using namespace std; #define INF 0x3f3f3f3f typedef long long ll; struct node { int v, dis; node(int v, int dis) { this->v = v, this->dis = dis; } }; vector<node> adj[1005]; int n, d[1005], num[1005];

ucler的博客 480

图论(四)——单源最短路径之Bellman-Ford算法和SPFA算法

单源最短路径问题,即给定一张有向图(其实无向图也可以看作是有向图,即将无向的一条边看成是两条有向的边),设1号节点为起点,求其到i号节点的最短距离 先来给出一个具体的题目,然后看看这两种算法是怎么写出代码来解决的 【使用Dijkstra算法的解决方案:图论(二)——单源最短路径之Dijkstra算法】 HDU最短路 Bellman-Ford算法 这个算法很好理解,它的操作的主要思想如下: ...

i_want_to_studyi的博客 325

【算法】单元最短路径之Bellman-Ford算法和SPFA算法

SPFA是经过对列优化的bellman-Ford算法,因此,在学习SPFA算法之前,先学习下bellman-Ford算法。 bellman-Ford算法是一种通过松弛操作计算最短路的算法。 适用条件 1.单源最短路径(从源点s到其它所有顶点v); 2.有向图&无向图(无向图可以看作(u,v),(v,u)同属于边集E的有向图); 3.边权可正可负(如有负权回路输出错误提示); 4.差...

Virtualman的专栏 182

单源最短路径和多源最短路径的四种算法及使用场景(Floyed + Dijkstra + Bellman-Ford + SPFA)---附Python实现实例

文章介绍Floyed + Dijkstra + Bellman-Ford + SPFA的使用场景,以及给出使用python实现的代码

qq_68630418的博客 1256

C/C++ 最短路径—Spfa-Bellman-Ford算法 (路径的保存和输出&负边判断)

一、最短路径 最短路径问题是图论研究中的一个经典算法问题, 旨在寻找图(由结点和路径组成的)中两结点之间的最短路径。 算法具体的形式包括: 确定起点的最短路径问题 - 即已知起始结点,求最短路径的问题。 确定终点的最短路径问题 - 与确定起点的问题相反,该问题是已知终结结点,求最短路径的问题。在无向图中该问题与确定起点的问题完全等同,在有向图中该问题等同于把所有路径方向反转的确定起点的问题。 确定起点终点的最短路径问题 - 即已知起点和终点,求两结点之间的最短路径。 全局最短路径问题 - 求图中所有的最

Carizy的博客 1003

Bellman-Ford算法和队列优化(SPFA)——求单源最短路径

来源自我的博客 http://www.yingzinanfei.com/2017/04/07/bellman-fordsuanfaheduilieyouhuaspfaqiudanyuanzuiduanlujing/ #include <stdio.h> #include <limits.h> int main(){ int n, m; scanf("%d%d", &n, &m);

陈止风的博客 904
上一篇: 最短路径算法----Floyd-warshall(十字交叉算法证明)
下一篇: 最小生成树----Prim算法+loose操作
圆形毕露
博客等级 码龄17年 20粉丝 103原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值