Bellman-ford算法与SPFA算法思想详解及判负权环(负权回路)
我们先看一下负权环为什么这么特殊:在一个图中,只要一个多边结构不是负权环,那么重复经过此结构时就会导致代价不断增大。在多边结构中唯有负权环会导致重复经过时代价不断减小,故在一些最短路径算法中可能会凭借不断重复经过负权环来得到权和为无穷小的最短路径,但因重复经过边不符合简单路径的定义导致这些算法跑最短路时要避免有负权环的出现。
这类算法说的就是Bellman-ford以及基于它进行优化的spfa了。由于负权环的出现导致这些算法的正确性失效。但这世上没有绝对的废物,我们也可以反过来利用这两种算法对负权环的敏感性来判断一个图内有无负权环。
结合一下这两个算法的原理,就能很简单地明白判负权回路的原理了:
1、Bellman-ford的原理即每次做一次枚举所有边进行一次大松弛操作后必有所有最短路径的第一条边(起点为源点的边)被确定(尽管我们并不确切地知道是哪一条边),被确定后,则会凭这条边再下一次大松弛操作再确定第二条边,以此类推。由于n个点的图的两点间最短路径最长有n条边,所以最多要n次大松弛就能把一个单源最短路求出(但实际上很多时候不到n次大松弛操作,就没有可松弛的了,即已经找到答案,可记录当前大松弛是否做过松弛操作,或基于该缺点改进为spfa)。但如果发现在n次大松弛操作后还有松弛操作可做,就说明负权回路出现了。时间复杂度O(nm)(m为边数),有点大。
2、SPFA则为针对Bellman-ford的缺点做的使每次做的松弛操作更有效的优化。发现在Bellman-ford第一次大松弛中只有松弛从源点出来的边才是有效的,松弛时当边的起点有效(被松弛过)时松弛操作才有效。那我们就不妨每次都只做有效的松弛操作,建一个队列,开始时将源点入队,每次从队头弹出head,尝试松弛所有head的邻接点,若松弛成功且该邻接点不在队中,就把它入队;否则什么也不干。时间复杂度为O(vm),v是一个平均值为2的常数。(因为当我们每次都做有效的松弛操作时,就会发现跑最短路快了很多,在大多数情况下可以吊打各个最短路算法。当然也特别容易被特殊数据卡,此时时间复杂度容易退化为O(nm))。类似的,spfa每做“一层”(层的概念类似于BFS的层)松弛操作就会确定所有最短路的一条边,故最极限的情况spfa做n层松弛操作就可以求出一个单源最短路了。
每层松弛操作只会导致一个点最多出队一次,由于最多只有n层,所以每个点的出队次数最多应不超过n。不幸的是,spfa的松弛操作碰上负权环时,会发现,从环的某一点a开始松弛其他点时,由于是负权环,所以绕了一圈回来后一定会发现a要被松弛为更小的值b(环外的点松弛环上的点只会使b更小),故就有无限循环松弛出现。记录每个点的出队次数,当发现有一个点的出队次数大于n,即为有负权环出现了。
善意的提醒:解题推理时从某个结构的基础组成部分入手并扩展,常常遇到惊喜~~~
Bellman-ford算法与SPFA算法思想详解及判负权环(负权回路)的更多相关文章
- 数据结构与算法--最短路径之Bellman算法、SPFA算法
数据结构与算法--最短路径之Bellman算法.SPFA算法 除了Floyd算法,另外一个使用广泛且可以处理负权边的是Bellman-Ford算法. Bellman-Ford算法 假设某个图有V个顶点 ...
- Bellman-Ford算法与SPFA算法详解
PS:如果您只需要Bellman-Ford/SPFA/判负环模板,请到相应的模板部分 上一篇中简单讲解了用于多源最短路的Floyd算法.本篇要介绍的则是用与单源最短路的Bellman-Ford算法和它 ...
- 最短路径——Bellman-Ford算法以及SPFA算法
说完dijkstra算法,有提到过朴素dij算法无法处理负权边的情况,这里就需要用到Bellman-Ford算法,抛弃贪心的想法,牺牲时间的基础上,换取负权有向图的处理正确. 单源最短路径 Bellm ...
- Bellman-ford算法、SPFA算法求解最短路模板
Bellman-ford 算法适用于含有负权边的最短路求解,复杂度是O( VE ),其原理是依次对每条边进行松弛操作,重复这个操作E-1次后则一定得到最短路,如果还能继续松弛,则有负环.这是因为最长的 ...
- 最短路径算法 4.SPFA算法(1)
今天所说的就是常用的解决最短路径问题最后一个算法,这个算法同样是求连通图中单源点到其他结点的最短路径,功能和Bellman-Ford算法大致相同,可以求有负权的边的图,但不能出现负回路.但是SPFA算 ...
- Floyd算法(一)之 C语言详解
本章介绍弗洛伊德算法.和以往一样,本文会先对弗洛伊德算法的理论论知识进行介绍,然后给出C语言的实现.后续再分别给出C++和Java版本的实现. 目录 1. 弗洛伊德算法介绍 2. 弗洛伊德算法图解 3 ...
- 最短路径算法之四——SPFA算法
SPAF算法 求单源最短路的SPFA算法的全称是:Shortest Path Faster Algorithm,该算法是西南交通大学段凡丁于1994年发表的. 它可以在O(kE)的时间复杂度内求出源点 ...
- 图论之最短路算法之SPFA算法
SPFA(Shortest Path Faster Algorithm)算法,是一种求最短路的算法. SPFA的思路及写法和BFS有相同的地方,我就举一道例题(洛谷--P3371 [模板]单源最短路径 ...
- 最短路径问题---Floyed(弗洛伊德算法),dijkstra算法,SPFA算法
在NOIP比赛中,如果出图论题最短路径应该是个常考点. 求解最短路径常用的算法有:Floyed算法(O(n^3)的暴力算法,在比赛中大概能过三十分) dijkstra算法 (堆优化之后是O(MlogE ...
随机推荐
- [19/10/16-星期三] Python中的模块和包、异常、操作文件
一.模块 # 模块(module) # 模块化,模块化指将一个完整的程序分解为一个一个小的模块 # 通过将模块组合,来搭建出一个完整的程序 # 不采用模块化,统一将所有的代码编写到一个文件中 # 采用 ...
- Python内置函数eval
英文文档: eval(expression, globals=None, locals=None) The arguments are a string and optional globals an ...
- 发布项目到github上web服务器来运行
$ git add dist Administrator@LuoTong- MINGW32 /D/react_workspace (master) $ git commit -m "git ...
- JSP总结(jsp/EL表达式/核心标签)
1.概念 jsp,即java Server Pages,java服务器页面. 2.简单介绍 小示例 <%@ page language="java" contentType= ...
- Linux yum 命令篇
yum( Yellow dog Updater, Modified)是一个在Fedora和RedHat以及SUSE中的Shell前端软件包管理器. 基於RPM包管理,能够从指定的服务器自动下载RPM包 ...
- 极*Java速成教程 - (5)
Java语言基础 容器 这个世界是有序的,将Java对象零散地放到内存中是不符合世界常理的,特别是有一大组相似的甚至不知道有多少数据的时候.把Java对象装进盒子里可以有序收纳,这个盒子就叫容器. 初 ...
- 运用swagger编写api文档
一.什么是swagger 随着互联网技术的发展,前后端技术在各自的道路上越走越远,他们之间的唯一联系变成了api接口,api接口文档编程了前后端人员的纽带,而swagger就是书写api文档的一款框架 ...
- SpringBoot整合mybatis碰到的问题
整合mybatis 1. 导包:在原有的web项目的基础上加上 <!--JDBC连接--> <dependency> <groupId>m ...
- RabbitMq学习2-php命令行模式测试rabbitmq
一.RabbitMQ结构 1.几个概念说明: Broker:简单来说就是消息队列服务器实体. Exchange:消息交换机,它指定消息按什么规则,路由到哪个队列. Queue:消息队列载体 ...
- Self-Driving Database
最近一直在做 ML in Database 相关的工作.偶然发现CMU 19spring的15-721课程竟然专门安排了这个专题,不禁欣喜若狂,赶紧去学习了一下. Andy提出了self-drivin ...