Dijkstra,Ford,SPF,Floyd,Johnson

8月份看懂,10月份忘光的节奏。。。。下文是8月份打的小笔记放草稿箱,下次有时间在整出来。。。标记下没看过的A*

Dijkstra:贪心算法,以点遍历.不适合负权,谁让他贪心到把负权忽略掉了,一般二叉堆实现寻找Min.后续会再看看非伯纳次(错别字,具体啥等看了再更正)堆实现方式.

留坑.

Ford:以边遍历,动态算法.适合负权,

留坑

SPF:对Ford进行的改进,有队列来优化

留坑

Floyd: 三层遍历的动态规划算法. i—>j的最短路径应该也为i—k + k—->j之和,如此循环切分,直到最初的图的邻接矩阵

所以该算法,将顶点一个个作为中间节点遍历

要理解,其实可以如此想,a节点先作为中间节点遍历了所有的节点对[i,j]对,得到了所有的以a为中间节点的[i,j]值

将b节点加入, 需得出以b为中间节点的所有顶点对的[i,j]最短路径,对于该算法,这一步可以转化成,寻找以,i–>b—>j(i,j直接连在b上) 或者 i–>a–>b—>j或者 i—>b—>a—>j或者i—>a—>b—>a—>j为中间节点的所有节点对,而这四种情况的任何子值都已经可以在第一次遍历以a为中间节点的循环中得出,i–>a–>b, b–>a–>j.所以其实就是各节点将a|b作为中间节点的最短路径值,a和b不需要同时存在一条最短路径上.

第三次循环的时候,可以当作将a,b,c三点作为中间节点得出来的最短路径值

以此到最后一次,可以得出所有顶点,以a|b|c|d|……|n为中间节点的值.

Johnson:Floyd算法用三重循环完成对每一对顶点间不断插入编号k++顶点的过程,最终求得每对顶点间顶点序号不大于numOfVertices的最短路径.
这对于稠密图来说很好.
但是如果图是稀疏的,那么边的数量很少,所以为了减少这个遍历插入所有顶点的过程,用了单源最短路径算法迪克拉斯算法+Bellman-Ford松弛算法,使问题反而变得更加简单。

Johnson算法可以在O(VElgV)时间内求解每对顶点之间的最短路径。对于稀疏图,该算法在要好于Floyd算法。算法与Floyd算法类似,每对顶点之间的最短距离用二维数组D表示;如果图中存在负环,算法将输出警告信息。Johnson算法把Bellman-Ford算法和Dijkstra算法作为其子函数。

在本节一开始我们提到,如果以每个顶点作为起始顶点,用Dijkstra算法求解单源最短路径,则可以求解全源最短路径,算法复杂度为VElgV。但是对含有负权值的图,Dijkstra算法将失效。Johnson算法运用了“重赋权”技术,即将原图中每条边的权值ω重新赋值为ω’,并且具有以下两个性质:

l 对所有顶点对u,v,路径p是以权值为ω的原图的最短路径,当且仅当路径p也是以权值为ω’的图的最短路径;

l 对于所有的边(u, v),ω’(u, v)是非负数。

重赋权后的图可以利用Dijkstra算法求解任意两个顶点之间的最短路径。稍后我们将会看到,重赋值不会改变最短路径,其处理复杂度为O(VE)。

下面我们将构造运算使得重赋权操作后得到的新的权值ω’满足上面提及的两个性质。

对带权有向图G=(V, E),边(u, v)的权值ω(u, v),设h为顶点映射到实数域的映射函数。对图中每条边(u, v),定义:

ω'(u, v) = ω(u, v) + h(u) – h(v)

在这样的构造运算可以满足第一条性质,即如果路径p=<v0, …, vk>是权值ω条件下顶点v0到vk的最短路径,那么p也是新权值ω’条件下的最短路径。用lenω(p)表示路径p在原图中的长度,lenω’(p)表示路径p在重赋权后的图中的长度,则

lenω’(p) = ω'(v0, v1) +ω'(v1, v2) + … + ω'(vk-1, vk)

  = [ω(v0, v1) + h(v0) – h(v1)] + [ω(v1, v2) + h(v1) – h(v2)]

+ … + [ω(vk-1, vk) + h(vk-1) – h(vk)]

  = ω(v0, v1) + ω(v1, v2) + … + ω(vk-1, vk) + h(v0) – h(vk)

  = lenω(p) + h(v0) – h(vk)

所以,如果权值为ω条件下顶点v0到vk存在一条更短的路径p*,那么对应地,在以权值为ω’的条件下,路径p*也比路径p更短。

再考虑第二条性质,即保证重赋权后权值非负。我们做如下的构造运算:

对给定的图G=(V, E),,边(u, v)的权值ω(u, v),构造一个新的图G’=(V’, E’),其中一个新的顶点s∉V,V’=V∪{s},E’=E∪{(s, u):u∈ V},对所有的u∈V,ω(s, u)=0。G’中没有以顶点s为终点的边,所以,如果G中不存在负环,那么G’中也不会存在负环。

在不存在负环的前提下,定义h(u)=lenmin(s, u),即顶点s到顶点u的最短路径,那么对所有的边(v, u)∈V’,h(u)≦ h(v) + ω(v, u)。那么在h(u)=lenmin(s, u)的条件下,便可满足ω'(u, v) = ω(u, v) + h(u) – h(v) ≧ 0,这样第二条性质便可满足。在上一节中我们讨论的Bellman-Ford算法能求解无负环的单元最短路径问题,可以用于求解h函数,其算法复杂度为O(VE)。

根据上面的讨论,Johnson算法结合Bellman-Ford算法和Dijkstra算法,包括以下几个步骤:

l 构造原图的扩展图G’=(V’, E’),V’=V∪{s},E’=E∪{(s, u):u∈ V};

l 在G’中以s为起始顶点应用Bellman-Ford算法,求解各顶点到顶点s的最短路径;

l 对原图重赋权;

l 重赋权后以图中每个顶点为起始顶点,应用Dijkstra算法求解每对顶点之间的最短路径;

l 由于重赋权改变了图中路径的长度,最后需要还原上一步骤中求得最短路径的长度;

点赞