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最短路算法
暑假,小哼准备去一些城市旅游.有些城市之间有公路,有些城市之间则没有,如下图.为了节省经费以及方便计划旅程,小哼希望在出发之前知道任意两个城市之前的最短路程. 上图中有 ...
随机推荐
- freemarker自己定义标签报错(二)
freemarker自己定义标签 1.错误描写叙述 freemarker.core.ParseException: Unexpected end of file reached. at freemar ...
- 【C】——pthread_mutex_lock
函数名 pthread_mutex_lock, pthread_mutex_trylock, pthread_mutex_unlock - lock and unlock a mutex SYNOPS ...
- 【oneday_onepage】——美国主食吃什么
Cocktail 鸡尾酒 It is quite usual to drink cocktails before lunch and dinner in America and somewhat le ...
- Reservoir Sampling - 蓄水池抽样问题
问题起源于编程珠玑Column 12中的题目10,其描述如下: How could you select one of n objects at random, where you see the o ...
- 总结这两天连续干掉的bug In 创新实训 智能自然语言交流系
临近项目合并,在pre合并中出现相当多的hug,遂记之 ps:这只是总结一下提纲,具体的方法在前文的博文中都详细记录.总结了. 平台的移植兼容性,虽然是跨平台的java,但是依旧有很多的意外: 1.从 ...
- altium designer 软件常用技巧总结(实时更新)
1.在使用altium designer画PCB时,在PCB界面画线找不到焊盘的中心点,将输入法切换到英文状态,按键盘D---O---勾选snap to object hotspots即可. 2.想高 ...
- 安装OpenSSL缺失Microsoft Visual C++ 2008 Redistributables的解决方案
在安装OpenSSL的时候通常会提示以下错误: "The Win32 OpenSSL Installation Project setup has detected that the fol ...
- 关于Unity中粒子效果的使用
粒子效果1: 游戏中会有很炫酷的特效,比如爆炸,水花,火焰等;2: unity提供粒子编辑器,方便特效人员来开发很炫酷的特效;3.粒子效果一般有专门的粒子特效师来做,我们只需要拿来用就好了,很多参数没 ...
- Pandas DataFrame 函数应用和映射
apply Numpy 的ufuncs通用函数(元素级数组方法)也可用于操作pandas对象: 另一个常见的操作是,将函数应用到由各列或行所形成的一维数组上.Dataframe的apply方法即可实现 ...
- 第三百三十九节,Python分布式爬虫打造搜索引擎Scrapy精讲—Scrapy启动文件的配置—xpath表达式
第三百三十九节,Python分布式爬虫打造搜索引擎Scrapy精讲—Scrapy启动文件的配置—xpath表达式 我们自定义一个main.py来作为启动文件 main.py #!/usr/bin/en ...