网站首页 > 技术教程 正文
前言
SPFA 算法由于它上限 O(NM) = O(VE) 的时间复杂度,被卡掉的几率很大.在算法竞赛中,我们需要一个更稳定的算法: dijkstra .
什么是 dijkstra ?
dijkstra 是一种单源最短路径算法,时间复杂度上限为 O(n^2) (朴素),在实际应用中较为稳定 ; 加上堆优化之后更是具有 O((n+m)\log_{2}n) 的时间复杂度,在稠密图中有不俗的表现.
dijkstra 的原理/流程?
dijkstra 本质上的思想是贪心,它只适用于不含负权边的图.
我们把点分成两类,一类是已经确定最短路径的点,称为"白点",另一类是未确定最短路径的点,称为"蓝点"
dijkstra 的流程如下 :
1. 初始化 dis[start] = 0, 其余节点的 dis 值为无穷大.
2. 找一个 dis 值最小的蓝点 x, 把节点 x 变成白点.
3. 遍历 x 的所有出边 (x,y,z), 若 dis[y] > dis[x] + z, 则令 dis[y] = dis[x] + z
4. 重复 2,3 两步,直到所有点都成为白点 .
时间复杂度为 O(n^2)
dijkstra 为什么是正确的
当所有边长都是非负数的时候,全局最小值不可能再被其他节点更新.所以在第 2 步中找出的蓝点 x 必然满足 :dis[x] 已经是起点到 x 的最短路径 . 我们不断选择全局最小值进行标记和拓展,最终可以得到起点到每个节点的最短路径的长度
图解
(令 start = 1 )
开始时我们把 dis[start] 初始化为 0 ,其余点初始化为 inf
第一轮循环找到 dis 值最小的点 1 ,将 1 变成白点,对所有与 1 相连的蓝点的 dis 值进行修改,使得 dis[2]=2,dis[3]=4,dis[4]=7
第二轮循环找到 dis 值最小的点 2 ,将 2 变成白点,对所有与 2 相连的蓝点的 dis 值进行修改,使得 dis[3]=3,dis[5]=4
第三轮循环找到 dis 值最小的点 3 ,将 3 变成白点,对所有与 2 相连的蓝点的 dis 值进行修改,使得 dis[4]=4
接下来两轮循环分别将 4,5 设为白点,算法结束,求出所有点的最短路径
时间复杂度 O(n^2)
为什么 dijkstra 不能处理有负权边的情况?
我们来看下面这张图
2 到 3 的边权为 -4 ,显然从 1 到 3 的最短路径为 -2 (1->2->3). 但在循环开始时程序会找到当前 dis 值最小的点 3 ,并标记它为白点.
这时的 dis[3]=1, 然而 1 并不是起点到 3 的最短路径.因为 3 已经被标为白点,所以 dis[3] 不会再被修改了.我们在边权存在负数的情况下得到了错误的答案.
dijkstra 的堆优化?
观察 dijkstra 的流程,发现步骤 2 可以优化
怎么优化呢?
我会zkw线段树!我会斐波那契堆!
我会堆!
我们可以用堆对 dis 数组进行维护,用 O(\log_{2}n) 的时间取出堆顶元素并删除,用 O(\log_{2}n) 遍历每条边,总复杂度 O((n+m)\log_{2}n)
范例代码:
例题
入门模板:P3371
进阶模板:P4779
其余例题请右转洛谷题库,搜索"最短路"
后记
本文部分内容摘自李煜东《算法竞赛进阶指南》和《信息学竞赛一本通》
友情提示:正权图请使用 dijkstra 算法,负权图请使用 SPFA 算法
感谢洛谷各位管理员提供的平台
本文发布于洛谷日报,特约作者:little_sun
原文地址:https://www.luogu.org/blog/61966/dijkstra
- 上一篇: 「洛谷日报第27期」点分治略解 点分什么意思
- 下一篇: 七律 巴夫洛谷的春天 巴夫洛logo
猜你喜欢
- 2024-10-05 七律 巴夫洛谷的春天 巴夫洛logo
- 2024-10-05 「洛谷日报第27期」点分治略解 点分什么意思
- 2024-10-05 洛谷刷题C++语言 | P1010 幂次方 c++次幂怎么输入
- 2024-10-05 洛谷刷题C++语言 | P1036 选数 洛谷p5714答案c语言
- 2024-10-05 洛谷刷题C++语言 | P1012 拼数 洛谷p5714答案c语言
- 2024-10-05 洛谷刷题C++语言 | P3392 涂国旗 c语言画国旗代码
- 2024-10-05 「洛谷日报第20期」浅谈基础根号算法——分块
- 2024-10-05 洛谷刷题C++语言 | P1102 A-B数对
- 2024-10-05 洛谷刷题C++语言 | P1443 马的遍历
- 2024-10-05 「洛谷日报第87期」浅谈并查集优化
你 发表评论:
欢迎- 05-1613步震撼淘宝大促闪光裂纹破墙立体字PS制作教程
- 05-16AI教程 | 绘制扁平的萌萌哒图标
- 05-160基础学平面设计所需了解的基础常识汇总
- 05-16自学平面设计需要多长时间?十六年职业设计总监告诉你
- 05-16平面设计都要学习哪些内容?
- 05-16李涛PS教程 高手之路PS教程 合成教程 —制作一个小星球
- 05-16Illustrator实例教程:制作炫酷的漩涡效果
- 05-16Illustrator实例教程:利用混合工具制作一朵炫酷的花
- 最近发表
- 标签列表
-
- sd分区 (65)
- raid5数据恢复 (81)
- 地址转换 (73)
- 手机存储卡根目录 (55)
- tcp端口 (74)
- project server (59)
- 双击ctrl (55)
- 鼠标 单击变双击 (67)
- debugview (59)
- 字符动画 (65)
- flushdns (57)
- ps复制快捷键 (57)
- 清除系统垃圾代码 (58)
- web服务器的架设 (67)
- 16进制转换 (69)
- xclient (55)
- ps源文件 (67)
- filezilla server (59)
- 句柄无效 (56)
- word页眉页脚设置 (59)
- ansys实例 (56)
- 6 1 3固件 (59)
- sqlserver2000挂起 (59)
- vm虚拟主机 (55)
- config (61)
本文暂时没有评论,来添加一个吧(●'◡'●)