关于最短路
前置知识:存图
又开了个史前巨坑
单源最短路
题意:给定源点
我们设当前已知的
我们考虑如何更新一条不那么优的路径。
比如下面
很显然,最短路径是
目前
那么我们就要用
也就是
(
用大白话,如果从 2 绕更短就从从 2 绕,否则就保持原来的路径。
此时
这个操作我们下面称为
显然
这个式子应该是所有最短路算法的核心。
后面的算法都可以去这里看代码。
Bellman-Ford
非常好理解,把每个边都
那为什么是 其实我也不太懂
在最短路存在的情况下,由于一次松弛操作会使最短路的边数至少
,而最短路的边数最多为 ,因此整个算法最多执行 轮松弛操作。
OIwiki上是这么说的。理解不了没关系,后面也用不到。
显而易见
SPFA
Shortest Path Faster Algorithm。
因为在
所以我们只需要按照
实际上只是减少了上面那个算法的
所以没负权别用 SPFA。复杂度
当然 SPFA 有个优化叫 SLF:
将普通队列换成双端队列,每次将入队结点距离和队首比较,如果更大则插入至队尾,否则插入队首。
这种优化相对不容易被卡,可以带上。
Dijkstra
最实用的单源最短路。
仍然是 bfs,但过程有所改变:
-
将队列换成优先队列(小根堆),每次将
入队时也将 入队,按 排序小根堆。 -
限制一个点多次入队,也就是遍历到
后 确定为最优。
那么有同学就有疑问了:为什么每次遍历到
我们先假设所有
当然,一开始
那么,当前优先队列的队头
所以我们可以确定,
既然
那么再下一步,肯定要走这个最小出边,否则从别的点绕一定更远。
那如果有负权,就不一定了。
如果有负权,那从别的点绕可能可以再走一个负权边回来,比走最小出边更好。
所以 Dijkstra 不能跑负权。
言归正传, Dijkstra 的过程就是:
- 找到
中所有点的最小出边连的点(原在 中),加入 中。 这个点的所有出边。
当然,原来的 Dijkstra 是暴力找最小出边连的点,这里用堆优化。
如果你看不懂正确性证明也没关系,毕竟贪心不需要证明
全源最短路
Floyd
有人不会吗?
dp[i][j]
表示
则有转移方程 dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j])(1≤k≤n)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具