2018.3.10 bellman-ford algorithm, floyd-warshall algorithm and johnson's algorithm

这周还是继续dynamic programming,不过回到了图算法,因为之前讲图算法的时候还没有讲到动态规划,而这三个算法要么本身是动态规划算法,要么要用到动态规划算法。

1.bellman-ford是一种求无负权值的环路的有向图两点间最小路径的算法,也就是说和dijkstra解决的是同一个问题。但是dijkstra无法计算有负权值的边时的情况,bellman-ford可以处理这种情况。如果给定的图有负权值的环路的话,那么就会出现负无穷大的最小路径,那当然是处理不了的,不过如果只有正权值的环路,那么bellman-ford是可以处理的。bellman-ford的核心trick是:从给定源点,到任何一点的最小路径,它的边数不应该超过n-1条。因为超过了的话就意味着至少经过了某个点两遍,那就意味着有负权值的环路,那么就不对了。

那么在知道了这个trick之后,我们就只需要做n-1次循环就可以了:初始化除源点以外的每个结点到源点的最小路径为正无穷大,然后每次循环,我们从源点向外延伸一条边,更新一次能延伸到的所有结点的最小路径。做n-1次循环后,得到的所有点的最小路径,就是我们要得到的结果。不过如果有负权值的环路的话,这个算法是不对的,但是也没关系,我们只需要再做一次这个循环,再延伸一条边,如果各点相对源点的最小路径有变化(也就是说有减小),那么根据某个我没看的证明(-_-!),这时就出现了负权值环路了,那么虽然算法不对,至少我们也检测到了负权值环路,知道了问题不可解。如果再做一次循环之后各点相对源点的最小路径没有变化,那就意味着没有负权值环路,那么得到的就是正确结果。

bellman-ford是O(mn)的,比dijkstra的O(mlg(n))慢不少,不过适用范围是更广的,而且据说还能分布式计算。

2.如果要计算一个给定有向图中,任意两点之间的最小路径,就是说每两点的组合都要求最小路径,那么很简单,跑n次bellman-ford就行了。不过这样子非常慢。floyd-warshall会更快一些的解决这个问题。floyd-warshall是一个很标准的dynamic programming算法。它把所有结点标记出编号1~n,那么从点i到点j的最小路径怎么求呢,我们像一般的动态规划的思路一样,把它变成subproblem,方法是从点i到点j的路径,只允许经过编号1~k-1的点,那么相对1~k,就是一个subproblem吧。

实际上这很像最早讲动态规划时举的max weight independent set的栗子,从up到bottom的过程中,每个subproblem相比上一个subproblem,只是多了一个编号为k的点是不是在路径中的选择。也就是说,这里是非常经典的两种方案的动态规划模型。对于从i到j,只允许经过1~k-1的最短路径的问题:如果k不在路径中,那么问题等同;如果k在路径中,那么把问题拆分为 “从i到k 加上 从k到j” 就解决了。

最后的算法是k,i,j从1到n的三层循环。复杂度为O(n^3),比跑n次bellman-ford的O(mn^2)要好,因为对于密集图,m最大是可以有n^2的。所以越密集的图,floyd-warshall的优势越大。

3.johnson‘s algorithm是解决什么问题呢,和floyd-warshall一样,也是解决给定图所有点组合间最小路径的问题的。我们之前说解决这个问题可以跑n次bellman-ford,虽然比较慢。johnson屌在哪呢,他实际上是跑了n次dijkstra来解决这个问题,而且这算法居然还能用在有负权值的边的情况!

trick在于,这算法是先用一种酷炫的方法把有负边的原图转化为没有负边的新图,然后对新图跑n边dijkstra,然后再把得到的新图的最短路径转化为原图的。

这里这种把有负边的原图转化为没有负边的新图的办法,叫做reweight technique。这个办法是:在原图基础上,加一个新结点,把新结点与原图的每个结点都用一条权值为0的边连通,然后以新结点为源点,对原图的各结点求最小路径——很显然,就是跑一遍bellman-ford。得到的每个最小路径,就是原图该结点的weight。这个weight能干啥呢:比如说原图有一条边,是从i到j,权值为负,那我们把权值加上i的weight,减去j的weight,得到的新权值,根据某个我没看的证明(-_-!!),这个新权值一定是正的。对原图所有的变都做这样的操作,那么就得到了一个所有边权值都为正的新图。

这个方法真的很吊,因为按这样去转化,任意两点之间的路径,其实只和原路径,以及这两个点的weight有关,和其他点的weight都没有关系,这样子后面往回转化的时候也非常好转化。

然后就是对新图n遍dijkstra了。得到的最短路径要变回去,这次减去i的weight,加上j的weight,就是原图的最短路径了。这个算法相当于1遍bellman-ford加n遍dijkstra,最后是O(mn lg(n))的,可以说是很快了。

2018.3.10 bellman-ford algorithm, floyd-warshall algorithm and johnson's algorithm

原文地址:https://www.cnblogs.com/dynasty919/p/8542972.html

时间: 2024-08-29 19:16:25

2018.3.10 bellman-ford algorithm, floyd-warshall algorithm and johnson's algorithm的相关文章

ACM/ICPC 之 最短路径-Bellman Ford范例(POJ1556-POJ2240)

两道Bellman Ford解最短路的范例,Bellman Ford只是一种最短路的方法,两道都可以用dijkstra, SPFA做. Bellman Ford解法是将每条边遍历一次,遍历一次所有边可以求得一点到任意一点经过一条边的最短路,遍历两次可以求得一点到任意一点经过两条边的最短路...如 此反复,当遍历m次所有边后,则可以求得一点到任意一点经过m条边后的最短路(有点类似离散数学中邻接矩阵的连通性判定) POJ1556-The Doors 初学就先看POJ2240吧 题意:求从(0,5)到

POJ 1860 Currency Exchange (Bellman ford)

Currency Exchange Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 22405   Accepted: 8095 Description Several currency exchange points are working in our city. Let us suppose that each point specializes in two particular currencies and pe

Bellman—Ford算法思想

---恢复内容开始--- Bellman—Ford算法能在更普遍的情况下(存在负权边)解决单源点最短路径问题.对于给定的带权(有向或无向)图G=(V,E),其源点为s,加权函数w是边集E的映射.对图G运行Bellman—Ford算法的结果是一个布尔值,表明图中是否存在着一个从源点s可达的负权回路.若存在负权回路,单源点最短路径问题无解:若不存在这样的回路,算法将给出从源点s到图G的任意顶点v的最短路径值d[v] Bellman—Ford算法流程 分为三个阶段: (1)初始化:将除源点外的所有顶点

Bellman - Ford 算法解决最短路径问题

Bellman - Ford 算法: 一:基本算法 对于单源最短路径问题,上一篇文章中介绍了 Dijkstra 算法,但是由于 Dijkstra 算法局限于解决非负权的最短路径问题,对于带负权的图就力不从心了,而Bellman - Ford算法可以解决这种问题. Bellman - Ford 算法可以处理路径权值为负数时的单源最短路径问题.设想可以从图中找到一个环路且这个环路中所有路径的权值之和为负.那么通过这个环路,环路中任意两点的最短路径就可以无穷小下去.如果不处理这个负环路,程序就会永远运

IntelliJ IDEA 最新激活码(截止到2018年10月14日)

IntelliJ IDEA 注册码: EB101IWSWD-eyJsaWNlbnNlSWQiOiJFQjEwMUlXU1dEIiwibGljZW5zZWVOYW1lIjoibGFuIHl1IiwiYXNzaWduZWVOYW1lIjoiIiwiYXNzaWduZWVFbWFpbCI6IiIsImxpY2Vuc2VSZXN0cmljdGlvbiI6IkZvciBlZHVjYXRpb25hbCB1c2Ugb25seSIsImNoZWNrQ29uY3VycmVudFVzZSI6ZmFsc2UsInBy

微软常用VC运行库合集(2018.4.10)X86X64

相信使用windows的小伙伴们都遇到过运行库报错的问题,尤其是使用绿色软件的时候,比如QQ和PS,由于在精简的时候把运行库精简掉了,所以难免会出现运行库报错.除了市面上的盗版ghost系统会内置运行库外,一般来说,微软原版的windows比较干净,没有集成运行库. 包含组件 * Visual Basic Virtual Machine(5.1) * Visual Basic Virtual Machine (6.0) * Microsoft C Runtime Library(7.0) * M

Python学习之路—2018/7/10

Python学习之路-2018/7/10 博客开发项目流程 ? 一般来说,一个项目的开发流程分为:项目需求.设计表结构.功能开发.测试功能.产品上线,本次学习以博客园为蓝本进行开发. 1.项目需求 博客的开发的需求主要有以下几点: 基于auth模块和Ajax实现登录验证 基于forms组件和Ajax实现注册功能 设计博客首页 设计个人站点页面 设计文章详情页面 实现文章点赞功能 实现文章的评论功能,包括对文章的评论以及对文章评论的评论 实现富文本编辑框 防止xss攻击(例如当用户的文章中含有JS

2018年10月小结(流水账) -- 1024程序员节快乐

2018年10月小结-- 1024程序员节快乐 今天刚好是1024程序员节.最近两个月没有更新博客,主要是最近有点迷茫,好像对技术丧失了热情,好像提不起兴趣.加上一些事情,感觉好累,好困,好迷茫.每当夜深人静的时候,有时会留下不知为什么的眼泪. 这两个月主要做基于公众号的WiFi故事机.原理很简单的,就是微信用户绑定一台故事机设备,然后公众号通过WebSocket发送命令到设备.实现微信互聊,故事点播,设备控制等简单功能.这个项目没什么技术含量的,至于卖的好不好暂时还不清楚. 就是这样一个一个小

What are the 10 algorithms one must know in order to solve most algorithm challenges/puzzles?

QUESTION : ANSWER: Dynamic Programming (DP) appears to account for a plurality (some estimate up to a third) of contest problems. Of course, DP is also not a single algorithm that you can just learn once and retain, so maybe this doesn't answer your