最短路径_Dijkstra_BellmanFord_SPFA_FloyedWarshall_Johnson

最短路径算法


以下归纳了几种常见算法,主要阐述总体思路,至于算法细节得大家自己写代码的时候进行探索了。(我一直觉得学习初期“思想”最重要)。
按我个人的理解,大部分最短路径算法隐含地维护一个“优先级队列”,每次取优先级高的点,不同之处在于“优先级的定义”。


Dijkstra

核心思想:BFS、贪心

数据结构:两个数组

  1. isShortest[ ],抵达该点是否已经找到最短路径(保存T/F),初始全F;
  2. Dis[ ],抵达该点的距离;初始infinite(除起点)。

基本过程:

  • Shortest[1]=T,从1开始“广度优先搜索”,更新Dis[];
  • 选择isShortest[i] = F && Dis[i]中“值最小”的点(即在未获得最短路径的点中找“距离值最小”的点),并将对应isShortest[i] = T,更新Dis数组;
  • 循环上一步至isShortest[]全T;

为什么对?:贪心贪心贪心,多数情况下局部最优相加就是全局最优。

缺点:不能包含负权。 因为该算法隐含着“路径次数”影响结果的思想,有负权时可能存在n+1步距离小于n步的距离,而该算法在n步时可能已经将该点划为“已寻找到最短路径”。
在这里插入图片描述

如上图,AC < AB,必然直接将isShortest[C]赋值为T,然后就错了…


BellmanFord

(可负权)
核心思想:BFS、DP。

数据结构:一个数组,Dis[ ],抵达该点距离;初始infinite(除起点)。

基本过程

和Dijkstra策略(判定条件)差不多,也是广度搜索+比较判定;
但是节点按顺序选择(依次遍历所有节点),也就是说我们不需要“先遍历值找到最小点”,使用DP而非贪心。

为什么对?:归纳法即可证明[1]


SPFA

(使用队列对BellmanFord算法进行改进)
基本过程:

每次从“队首节点”搜索,将距离变小的点放入队列(它变小了,所以有理由怀疑它能影响其他点),
然后弹出队首元素并循环,最后队列无点结束。

为什么对?:事实上这个算法在某些时候不对哈哈哈哈哈,如网格图。


Tips

  • Dijkstra基于贪心,每次从“值最小点”出发;也就是说每次都必须从“局部最优”走;
  • BellmanFord使用DP,遍历新点对所有“距离”进行重新计算(动态规划);每次遍历新点算法也不知道是否为最优解,对点一视同仁,不断更新就完事了;
  • 其中Dijkstra最常用,优化策略也有不少,例如堆优化策略;
  • SPFA可以在“加入队列”这一步增加“判定条件”进行优化。但非常不推荐该算法[2],在 NOI2018 Day1 T1归程中正式被卡,其时间复杂度为O(nm),远劣于Dijkstra的O((n+m)log m))。

以上都是SSP(Single-source Shortest Path,单源最短路径),接下来介绍APSP(All Pairs Shortest Paths,多源最短路径)。


FloydWarshall

(可处理负权(但不可存在负权回路)):
核心思想:DP。

数据结构:两个数组(都是对称的矩阵):

  1. Dis[ ][ ],邻接矩阵;
  2. Path[ ][ ],路径中间节点,这个矩阵甚至不需要,作用为记录路径。举例:Path[0][9]=5,表示“点0到点9最短路径”=“点0到点5最短路径”+“点5到点9最短路径”,然后“递归”即对“点0到点5最短路径”和“点5到点9最短路径”分别进一步展开, 如下图所示。
    在这里插入图片描述

基本过程: 三层循环

 for(每个点)
     for(矩阵横坐标)
         for(矩阵纵坐标)
              if判断,然后更新俩矩阵;

为什么对?:同BellmanFord。


Johnson

(可处理负权)
核心思想:rewight(对距离进行变换),消除负边,然后用Dijkstra,所以说成Dijkstra的优化也未尝不可。

基本过程:

  1. 增加一个新的顶点 s,使 s 指向图 G 中的所有顶点都建立连接,设新图为 G’;
  2. 对图 G’ 中顶点 s 使用BellmanFord计算单源最短路径,得到结果 h[] = {h[0], h[1], … h[V-1]};
  3. 对原图 G 中的所有边进行 “reweight”,即对于每个边 (u, v),其新的权值为 w(u, v) + (h[u] - h[v]); 移除新增的顶点 s,对“每个顶点”运行Dijkstra求得最短路径;

Reference:
[1]:Floyd算法正确性的证明
[2]:如何看待 SPFA 算法已死这种说法? - 知乎 (zhihu.com)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值