Lecture 23

绪论

前面我们介绍了解决单源结点最短路径问题的算法——Bellman-ford算法和Dijkstra算法,解决单个结点到单个结点最短路径问题的算法——A*算法。

但如果我们需要求大量的单个结点到单个结点的最短路径,并且起点和终点并不集中于某一个结点,进行|V|次的Dijkstra算法或Bellman-ford算法和进行|V|2次的A*算法(这种方法的效率不如Floyd算法存疑)在稠密图(O(|E|)=O(|V|2))中的复杂度逼近O(|V|3log|V|)。

我们这一章节介绍的Floyd算法能够在O(|V|3)的复杂度解决上述求解稠密图中多组单个结点到单个结点最短路径的问题。


Strategy

Floyd算法从实现和策略上来看其实非常简单,就思想上来看我个人觉得和Bellman-ford算法有一点类似(动态规划的思想)。

回想Bellman-ford算法求解单源结点最短路径问题的过程,是每次将从某个结点出发经过边数小于等于k的最短路径扩展到边数小于等于k+1的最短路径(松弛操作),进行|V|-1次松弛操作得到一个结点到所有结点的最短路径。

Floyd算法从经过哪些结点这方面考虑各个结点之间的最短路径,我们初始化的邻接矩阵,结点之间的路径相当于不经过另外任何点的最短路径。

在这里插入图片描述

如果我们现在允许某个结点是可以经过的,那么可能会产生的u到v的新的最短路径相当于u到0的最短路径和0到v的最短路径,和Bellman-ford算法一样相当于继承了两段的最短路径,我们只需要让每条结点之间的最短路径进行一次可能的更新即可。

下面是允许编号为0的结点可以经过:

在这里插入图片描述
同理我们可以在允许最短路径经过编号为0的结点的基础上,允许经过编号为1的结点(同样的操作),我们最后需要求结点之间的最短路径希望能够允许经过编号的结点,即对各个结点都进行一次上面的操作。

Floyd算法即如下:

在这里插入图片描述

这个过程很像在结点之间的最短路径上允许插入其余|V|-2的结点,所以Floyd算法又称插点法(Floyd算法也是不能在负环存在的图中进行的)。

需要求出路径的方法Bellman-ford算法求出路径的方法是一样的,用p[i][j]记录i到j的最短路径上i结点的后继结点,因为Floyd算法和Bellman-ford算法一样都相当于继承了前面的最短路径,在结点i到结点j的最短路径因为允许通过节点k(插入结点k)发生改变时,结点i到结点j的最短路径继承结点i到结点k和结点k到结点j的最短路径,结点i的结点j的最短路径上结点i的后继节点继承结点i到结点k的最短路径上结点i的后继结点。

(虽然我个人觉得如果时用p数组,不是更应该是前继结点?parent?)

在这里插入图片描述

在这里插入图片描述


总结

是的,Floyd算法就这么一点内容hhhhh。

事实上Floyd算法在求解最短路径问题适用的情况比较苛刻,相较而言前面几种算法用的更多。Floyd更多用于计算离散数学二元关系中求解传递闭包的问题。

有趣的是,搜了一下资料发现Floyd算法作为求解传递闭包的算法提出的比Bellman-ford算法还要早(非正式提出),就是说时间顺序上应该是Floyd算法->Bellman-ford算法->Dijkstra算法。我个人觉得Bellman-ford算法是Dijkstra算法的基础,Dijkstra算法是建立在Bellman-ford算法的优化,至于Bellman-ford算法是否脱胎于Floyd算法或者说动态规划思想,继承最短路径,从中间扩展和向外扩展········,这我们就不得而知了hhhh(至少大部分书上介绍的顺序都是:Dijkstra算法->Bellman-ford算法->Floyd算法)。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值