Floyd 和 bellman 算法
Floyd-Warshall算法(Floyd-Warshall algorithm)是解决任意两点间的最短路径的一种算法,可以正确处理有向图或负权的最短路径问题,同时也被用于计算有向图的传递闭包。
Floyd-Warshall算法的时间复杂度为,空间复杂度为
。
原理
Floyd-Warshall算法的原理是动态规划。
设为从
到
的只以
集合中的节点为中间节点的最短路径的长度。
- 若最短路径经过点k,则
;
- 若最短路径不经过点k,则
。
因此,。
在实际算法中,为了节约空间,可以直接在原来空间上进行迭代,这样空间可降至二维。(见下面的算法描述)
算法描述
Floyd-Warshall算法的描述如下:
for k ← to n do
for i ← to n do
for j ← to n do
if (D_{i,k} + D_{k,j} < D_{i,j}) then
D_{i,j} ← D_{i,k} + D_{k,j};
其中表示由点
到点
的代价,当
为 ∞ 表示两点之间没有任何连接。
Floyd-warshall 算法总结
1. 初始化时, 将 dp[i][i] 设置为 0
2. i, j 均从 1 开始遍历
3. 从状态转移方程到代码的实现, 最关键的一步是确定最外层的循环变量是谁, 而最外层的循环变量又是从状态转移方程本身推出. 比如在 Floyd 算法中, 状态转移方程是
当 k 在最短路径上时, dp(i, j, k) = dp(i, k, k-1) + dp(k, j, k-1)
当 k 不在最短路径时, dp(i, j, k) = dp(i, j, k-1)
可以转化为 g(k) = f(k, k-1), 因此应该把 k 作为最外层的循环变量
4. 空间压缩. 在求解 dp(i, j, k) 时, 会用到 dp(i, k, k-1) 和 dp(k, j, k-1) 以及 dp(i, j, k-1). 新生成的数据 dp(i, j, k) j != k 不会被重复利用, 因此可以使用二维空间
Bellmanford 算法
1. 与 Dijsktra 算法的比较. D 是一种贪心算法, 贪心策略为选取未被处理的最短的节点, 理由是该节点有潜力更新某些节点的距离, 使之变得更小, 每次对该节点的出边进行松弛. 而 B 算法简单的对所有的边进行松弛, 可以看出, D 算法进行的运算是 B 算法的子集. B 算法的优点是不仅可以处理负权边, 还能判断图是否存在负环.
2. 松弛. 松弛实际上是对相邻节点的访问, 第 n 次松弛保证了保证了所有深度为 n 个节点得出了最短路径. 由于图最短路径最深至多是 V-1, 因此 V-1 次松弛即可确定所有点的最短路径
3. 负权环判定. 因为负权环可以无限制的拉低最短路径, 因此在进行第 V 次松弛后, 最短路径值有所减小, 那么可以肯定, 存在负权环
4. 朴素 BellmanFord 算法
procedure BellmanFord(list vertices, list edges, vertex source)
// 该实现读入边和节点的列表,并向两个数组(distance和predecessor)中写入最短路径信息 // 步骤1:初始化图
for each vertex v in vertices:
if v is source then distance[v] :=
else distance[v] := infinity
predecessor[v] := null // 步骤2:重复对每一条边进行松弛操作
for i from to size(vertices)-:
for each edge (u, v) with weight w in edges:
if distance[u] + w < distance[v]:
distance[v] := distance[u] + w
predecessor[v] := u // 步骤3:检查负权环
for each edge (u, v) with weight w in edges:
if distance[u] + w < distance[v]:
error "图包含了负权环"
5. SPFA 优化
SPFA 是 Shorest Path Faster Algorithm 的简写. SPFA 基于一个事实: 松弛有效的操作必然发生在松弛的前导节点成功松弛的节点上.
用一个队列记录松弛过的节点, 可以减少冗余计算, 将复杂度降低到 o(kE)
Begin
initialize-single-source(G,s);
initialize-queue(Q);
enqueue(Q,s);
while not empty(Q) do
begin
u:=dequeue(Q);
for each v∈adj[u] do
begin
tmp:=d[v];
relax(u,v);
if (tmp<>d[v]) and (not v in Q) then
enqueue(Q,v);
end;
end;
End;
Floyd 和 bellman 算法的更多相关文章
- 数据结构与算法--最短路径之Bellman算法、SPFA算法
数据结构与算法--最短路径之Bellman算法.SPFA算法 除了Floyd算法,另外一个使用广泛且可以处理负权边的是Bellman-Ford算法. Bellman-Ford算法 假设某个图有V个顶点 ...
- SGU 455 Sequence analysis(Cycle detection,floyd判圈算法)
题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=455 Due to the slow 'mod' and 'div' operati ...
- 最短路径问题——bellman算法
关于最短路径问题,最近学了四种方法——bellman算法.邻接表法.dijkstra算法和floyd-warshall算法. 这当中最简单的为bellman算法,通过定义一个边的结构体,存储边的起点. ...
- Bellman算法
Bellman算法 当图有负圈的时候可以用这个判断最短路! [时间复杂度]O(\(nm\)) &代码: #include <bits/stdc++.h> using namespa ...
- Floyd最短路算法
Floyd最短路算法 ----转自啊哈磊[坐在马桶上看算法]算法6:只有五行的Floyd最短路算法 暑假,小哼准备去一些城市旅游.有些城市之间有公路,有些城市之间则没有,如下图.为了节省经费以及方便计 ...
- UVA 11549 CALCULATOR CONUNDRUM(Floyd判圈算法)
CALCULATOR CONUNDRUM Alice got a hold of an old calculator that can display n digits. She was bore ...
- UVA 11549 Calculator Conundrum (Floyd判圈算法)
题意:有个老式计算器,每次只能记住一个数字的前n位.现在输入一个整数k,然后反复平方,一直做下去,能得到的最大数是多少.例如,n=1,k=6,那么一次显示:6,3,9,1... 思路:这个题一定会出现 ...
- leetcode202(Floyd判圈算法(龟兔赛跑算法))
Write an algorithm to determine if a number is "happy". 写出一个算法确定一个数是不是快乐数. A happy number ...
- 【啊哈!算法】算法6:只有五行的Floyd最短路算法
暑假,小哼准备去一些城市旅游.有些城市之间有公路,有些城市之间则没有,如下图.为了节省经费以及方便计划旅程,小哼希望在出发之前知道任意两个城市之前的最短路程. 上图中有 ...
随机推荐
- CubieTruck入手第一天
基本的參考资料整理例如以下: mod=viewthread&tid=160" id="thread_subject" style="word-wrap: ...
- 【C】——setjmp练习
#include<setjmp.h> int setjmp(jmp_buf env); 返回值:若直接调用则返回0,若从longjmp调用返回则返回非0值 void longjmp(jmp ...
- 服务器cpu过高修复:操作系统内核bug导致
服务器cpu过高修复:操作系统内核bug导致修改系统内核参数/etc/sysctl.conf添加下面2条参数:vm.dirty_background_ratio=5vm.dirty_ratio=10
- jquery+easyui开发、培训文档
目 录 1.... Accordion(可折叠标签)......................................................................... ...
- 安卓程序代写 网上程序代写[原]C语言基础
C 作者:han1202012 发表于2013-11-1 19:53:29 原文链接 阅读:28 评论:0 查看评论
- Debug 单步执行命令step into/step out/step over的区别
总结一下在debug中三种调试的区别: step into就是单步执行,遇到子函数就进入并且继续单步执行: step over是在单步执行时,在函数内遇到子函数时不会进入子函数内单步执行,而是将子函数 ...
- linux中怎么查看ip地址
命令 ifconfig 可以查看当前主机的ip地址: 如果要手动更改ip地址. 可以输入命令cd /etc/sysconfig/network 在这个目录下会有 类似于ifcfg-@@的文件. 可以用 ...
- 第三百五十七节,Python分布式爬虫打造搜索引擎Scrapy精讲—利用开源的scrapy-redis编写分布式爬虫代码
第三百五十七节,Python分布式爬虫打造搜索引擎Scrapy精讲—利用开源的scrapy-redis编写分布式爬虫代码 scrapy-redis是一个可以scrapy结合redis搭建分布式爬虫的开 ...
- e811. 创建具有嵌套菜单的弹出式菜单
See e810 创建弹出菜单 for an example on how to display a popup menu. final JPopupMenu popupMenu = new JPop ...
- AWT控件称为重量级控件
AWT 是Abstract Window ToolKit (抽象窗口工具包)的缩写,这个工具包提供了一套与本地图形界面进行交互的接口. AWT 中的图形函数与操作系统所提供的图形函数之间有着一一对应的 ...