斯坦福 算法2 第四周笔记

来自斯坦福网站的Algorithms: Design and Analysis,与目前coursera上的版本内容没有变化,不过时间安排略有不同。

1. Bellman-Ford Algorithm

单源最短路径算法指的是从给定的输入图G中根据起始点s和目标点v输出一条s到v的距离最短的路径。

Dijkstra算法之前讲过的一个单源最短路径的算法。这个算法优点在于它的运行速度可以使 O ( m l o g n ) O(mlogn) O(mlogn)的。但是缺点也很明显:1)它在有负长度的边时不一定正确。2)它需要起始点能够知道所有的结点信息,无法分布式运行。

还有一个更严重的问题,那就是图中可能存在权重和为负数的环。如果存在这样的环,那么最短路径算法的运行可能会有问题。而对于一个单源最短路算法来说,它要么输出一条s到v的最短路径,要么输出一个负权重的环。

1.1 算法

假如我们想用动态规划的思想来解决这个问题,那么就需要先观察一下最优解的结构。虽然图这个结构没有一个合适的分解为更小问题的顺序,但是路径天然存在这个顺序,因此我们观察可能存在的最优解路径的结构。
在这里插入图片描述
由于路径带来的顺序与其长度有关系,因此我们可以看到当最优路径长度为i时,与结点数为i-1时的关系。这个关系分为两种情况。

这两种关系的正确性证明如下:
在这里插入图片描述
根据对于最优路径结构的观察,我们能够写出解法的递推形式:
在这里插入图片描述
这个递推中利用 L i , v L_{i,v} Li,v表示出当路径长度最大为i时到达点v的路径的最小值。在这个表示的基础上根据上面的结构关系进行递推。而且我们发现,如果图中不含有负权重的路径,那么整个图中的最短路径长度最多是n-1,也就是说这个递推关系到i=n-1的时候就可以结束了。

算法流程如下,算法复杂度为 O ( m n ) O(mn) O(mn)
在这里插入图片描述

1.2 负权重环问题

我们还发现这个算法实际上是能够解决负权重环问题的。我们有如下的假设:
在这里插入图片描述
也就是说只要上面的算法进行到i=n的时候还有更新,那么就说明这个图中存在可以从s到达的负权重环。这两个命题互为充要条件。

从左到右实际上就是Bellman-Ford算法在不存在负权重环时候的正确性证明。而从右往左的证明如下:
在这里插入图片描述

1.3 空间压缩

这个算法需要的二维数组空间复杂度是 O ( n 2 ) O(n^{2}) O(n2)。但是实际上我们从递推过程发现每次的A[i,v]只需要A[i-1,v]就可以完成更新。因此实际上可以将空间复杂度压缩为 O ( n ) O(n) O(n)级别的。

但是压缩了之后有个问题就是无法从这个一维权重数组中重建出整条最短路径。于是需要为每个结点添加一个额外的信息,那就是在最短路径上的前一个结点B[i,v],而这个结点数组也是 O ( n ) O(n) O(n)的,它的更新过程如下:
在这里插入图片描述
实际上有了这个节点信息之后,我们还可以将遇到的负权重环直接输出得到:
在这里插入图片描述
具体的就是在将算法执行到i=n步之后,如果确认负权重环的存在,然后从B数组中进行DFS即可。

2. All-Pairs Shortest Paths

这个问题的定义如下:
在这里插入图片描述
也就是输出所有可能的结点对之间的最短路径,或者输出存在负环。

根据已有的算法实际上已经能够解决这个问题,那就是调用n次已知的单源最短路径算法。两种算法对应稀疏图和稠密图时候复杂度如下:
在这里插入图片描述
但是我们希望能够有一种更好的算法,在稠密图中也能够得到 O ( n 3 ) O(n^{3}) O(n3)的复杂度,而且还需要能够解决负环的问题。

2.1 Floyd-Wayshall algorithm

这就是Floyd-Wayshall算法的动机。如果利用动态规划的思想来观察这个问题的最优解的结构,我们需要确立一个顺序以便找到递推关系。可以考虑类似于背包问题时候将无序的每个石头编号,因此这里将每个结点编号。

同样的这个顺序肯定是由路径来决定,我们假设路径P只能由编号1到编号k的结点得到(不包括起始点)。
在这里插入图片描述
于是我们得到了路径P的递推关系,同样也分为两种情况。一种是编号为k的结点在最优路径P中间,另一种是k结点不在最优路径上。
在这里插入图片描述
如果用三维数组A[i,j,k]表示结点i到结点j只能用编号前k个结点时候最短路径的权重和,那么就能够得到以下算法:
在这里插入图片描述
还有两个问题:1)遇到负环怎么办?答:遇到负环比如存在A[i,i,k]=0的情况,以此判断。 2)如何重建最短路径?答:利用二维数组B[i,j]表示从i到j路径 上的最大编号的结点。得到的是k那么就根据B[i,k]和B[k,j]的结果来递归重建最短路。

2.2 Johnson’s algorithm

上面的算法对于稀疏图稠密图都是需要三次方的复杂度。但是我们知道调用n次Dijkstra算法的复杂度会优于这个算法。而调用n次Bellman-Ford算法又能解决Dijkstra算法不能解决的负权重的问题。是否可以将它们的优点结合一下?
在这里插入图片描述
Johnson的算法本质上依然是使用n次Dijkstra算法,那么如何解决负权重的问题呢?那就是为每条边重新构建一个非零权重。我们知道直接对每个权重加同一个数基本上无法保证算法正确性,这里的重新赋权重很有技巧。

首先将所有的结点赋一个值 p v p_{v} pv,而将每条边(u,v)的新权重赋值为 c e ′ = c e + p u − p v c_{e}'=c_{e}+p_{u}-p_{v} ce=ce+pupv,这样对于每一条从s到v的路径来说,新的权重和 L ′ = L + p s − p v L'=L+p_{s}-p_{v} L=L+pspv,这里的L是旧权重的路径权重和。因此如此赋值之后不会改变最短路径的结果。

但是我们的目标是让每条边都变为非负权重,那么如何做到这一点?很好的一点是,Bellman-Ford算法能够帮我们完成。

先看一个Bellman算法改变图中边权重的例子:
在这里插入图片描述
在原始的图外加一个额外的结点s,s与其它每个结点相连而且权重均为0。然后以s为起点运行Bellman-Ford算法,得到每个结点到达s的距离。

把这个距离作为每个结点新增的值 p v p_{v} pv,然后更新边的权值。
在这里插入图片描述
更新了之后图中所有的边权值都非负,因此可以在后面调用dijkstra算法解决。于是我们就知道了Johnson算法的流程:
在这里插入图片描述
注意最后一步还要将路径权重和还原成真实的权重和。

这个算法的复杂度是 O ( m n l o g n ) O(mnlogn) O(mnlogn)的,在稀疏图中有比Floyd算法更好的性能。
在这里插入图片描述
算法的正确性建立在更新后的权值均为非负的假设上,因此只需要证明更新后边的权值均为非负即可。
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值