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最短路算法
暑假,小哼准备去一些城市旅游.有些城市之间有公路,有些城市之间则没有,如下图.为了节省经费以及方便计划旅程,小哼希望在出发之前知道任意两个城市之前的最短路程. 上图中有 ...
随机推荐
- php 扫描 下载 apk
$file = 'C:\WebSiteDirectory\CarparkWeixinBackend\Dplus.apk'; if (file_exists($file)) { header('Cont ...
- C#注册表读写完整操作类
1.注册表基项静态域 /// <summary> /// 注册表基项静态域 ///1.Registry.ClassesRoot 对应于HKEY_CLASSES_ROOT 主键 ///2.R ...
- Sword protobuf学习四
#include <iostream> #include <string> #include <sys/types.h> /* See NOTES */ #incl ...
- window.showModalDialog乱码(完美)解决方案
关于jsp弹出jsp页面传参数中文乱码的问题解决: 弹出方式--window.showModalDialog(requestURL,null,strFeatureInfo); 乱码原因:url传递方式 ...
- Android WiFi 日志记录(ASSOC_REJECT)
记录Android N关联拒绝之后的相关的log. 10-26 20:35:35.844 2215 2215 D wpa_supplicant: * bssid_hint=44:48:c1:d6:57 ...
- MySQL存储过程、触发器 小例子
一.存储过程 语法: CREATE PROCEDURE([[IN |OUT |INOUT ] 参数名 数据类形...]) BEGIN ... END 参数: IN 输入参数 表示该参数的值必须在调用存 ...
- Java与编码问题串讲之二–如何理解java采用Unicode编码
Java开发者必须牢记:在Java中字符仅以一种形式存在,那就是Unicode(不选择任何特定的编码,直接使用他们在字符集中的编号,这是统一的唯一方法).由于java采用unicode编码,char ...
- Android多任务切换与Activity启动模式SingleTask之间关系的分析
这里会以多个场景列子进行分析,在分析之前先了解一下基本的概念. Task任务:一系列Activity的集合,这些Activity以栈的形式进行排列(后进先出). 那在什么时候系统会新建一个Task任务 ...
- PHP中全局变量的使用global和$GLOBALS[]
From: http://blog.csdn.net/happyqyt/article/details/7219889 用PHP开发项目,不可避免的会使用到全局变量,比如一些网站的配置信息,全站通用, ...
- Making ARC and non-ARC files play nice together
From Codeography If you want to exclude a file from being compiled with ARC you can do so by setting ...