我们先看一下负权环为什么这么特殊:在一个图中,只要一个多边结构不是负权环,那么重复经过此结构时就会导致代价不断增大。在多边结构中唯有负权环会导致重复经过时代价不断减小,故在一些最短路径算法中可能会凭借不断重复经过负权环来得到权和为无穷小的最短路径,但因重复经过边不符合简单路径的定义导致这些算法跑最短路时要避免有负权环的出现。

这类算法说的就是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算法思想详解及判负权环(负权回路)的更多相关文章

  1. 数据结构与算法--最短路径之Bellman算法、SPFA算法

    数据结构与算法--最短路径之Bellman算法.SPFA算法 除了Floyd算法,另外一个使用广泛且可以处理负权边的是Bellman-Ford算法. Bellman-Ford算法 假设某个图有V个顶点 ...

  2. Bellman-Ford算法与SPFA算法详解

    PS:如果您只需要Bellman-Ford/SPFA/判负环模板,请到相应的模板部分 上一篇中简单讲解了用于多源最短路的Floyd算法.本篇要介绍的则是用与单源最短路的Bellman-Ford算法和它 ...

  3. 最短路径——Bellman-Ford算法以及SPFA算法

    说完dijkstra算法,有提到过朴素dij算法无法处理负权边的情况,这里就需要用到Bellman-Ford算法,抛弃贪心的想法,牺牲时间的基础上,换取负权有向图的处理正确. 单源最短路径 Bellm ...

  4. Bellman-ford算法、SPFA算法求解最短路模板

    Bellman-ford 算法适用于含有负权边的最短路求解,复杂度是O( VE ),其原理是依次对每条边进行松弛操作,重复这个操作E-1次后则一定得到最短路,如果还能继续松弛,则有负环.这是因为最长的 ...

  5. 最短路径算法 4.SPFA算法(1)

    今天所说的就是常用的解决最短路径问题最后一个算法,这个算法同样是求连通图中单源点到其他结点的最短路径,功能和Bellman-Ford算法大致相同,可以求有负权的边的图,但不能出现负回路.但是SPFA算 ...

  6. Floyd算法(一)之 C语言详解

    本章介绍弗洛伊德算法.和以往一样,本文会先对弗洛伊德算法的理论论知识进行介绍,然后给出C语言的实现.后续再分别给出C++和Java版本的实现. 目录 1. 弗洛伊德算法介绍 2. 弗洛伊德算法图解 3 ...

  7. 最短路径算法之四——SPFA算法

    SPAF算法 求单源最短路的SPFA算法的全称是:Shortest Path Faster Algorithm,该算法是西南交通大学段凡丁于1994年发表的. 它可以在O(kE)的时间复杂度内求出源点 ...

  8. 图论之最短路算法之SPFA算法

    SPFA(Shortest Path Faster Algorithm)算法,是一种求最短路的算法. SPFA的思路及写法和BFS有相同的地方,我就举一道例题(洛谷--P3371 [模板]单源最短路径 ...

  9. 最短路径问题---Floyed(弗洛伊德算法),dijkstra算法,SPFA算法

    在NOIP比赛中,如果出图论题最短路径应该是个常考点. 求解最短路径常用的算法有:Floyed算法(O(n^3)的暴力算法,在比赛中大概能过三十分) dijkstra算法 (堆优化之后是O(MlogE ...

随机推荐

  1. 20191128 Spring Boot官方文档学习(9.10)

    9.10.数据库初始化 可以使用不同的方式初始化SQL数据库,具体取决于堆栈是什么.当然,如果数据库是一个单独的进程,您也可以手动执行.建议使用单一机制进行模式生成. 9.10.1.使用JPA初始化数 ...

  2. 【css】子元素浮动到了父元素外,父元素没有随子元素自适应高度,如何解决?

    正常情况 如果子元素没有设置浮动(float),父元素的高度会随着子元素高度的改变而改变的. 设置浮动以后 父元素的高度不会随着子元素的高度而变化. 例如:在一个ul中定义若干个li,并设置float ...

  3. 【C语言--数据结构】线性表链式存储结构

    直接贴代码 头文件 #ifndef __LINKLIST_H__ #define __LINKLIST_H__ typedef void LinkList; typedef struct _tag_L ...

  4. spring mvc + xmlHttpRequest2.0 实现无刷新上传文件,带进度条和剩余时间

    1.springmvc支持文件上传,需要在spring-mvc.xml配置文件中加上下面的一段话: <!-- 支持上传文件 --> <bean id="multipartR ...

  5. CF682C Alyona and the Tree

    题意翻译 题目描述 给你一棵树,边与节点都有权值,根节点为1,现不停删除叶子节点形成新树,问最少删掉几个点,能使得最后剩下的树内,∀v与其子树内∀u间边权的和小于点u权值 输入输出格式 输入格式: 第 ...

  6. python 发送kafka

    python 发送kafka大体有三种方式 1 发送并忘记(不关注是否正常到达,不对返回结果做处理) 1 import pickle 2 import time 3 from kafka import ...

  7. 使用SQL语法来查询Elasticsearch:Elasticsearch-SQL插件

    简介 Elasticsearch-SQL是Elasticsearch的一个插件,它可以让我们通过类似SQL的方式对Elasticsearch中的数据进行查询.项目地址是:https://github. ...

  8. Spring的底层实现机制

    Spring的底层实现机制是通过Demo4j+java反射机制实现的. 使用demo4j来解析xml,使用反射机制实例化bean.

  9. python 二分法实现

    # -*- coding: utf-8 -*- def BinarySearch(arr, key): # 记录数组的最高位和最低位 min = 0 max = len(arr) - 1 if key ...

  10. 时间戳转换日期格式 - Vue

    日常开发中经常会遇到时间相关的问题,服务端返回的数据都是以时间戳的方式,那么需要将其处理转化为对应的时间格式,具体方式如下: 一.filters 中 formatDate 方法实现 <scrip ...