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=
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 由于重赋权改变了图中路径的长度,最后需要还原上一步骤中求得最短路径的长度;