问题描述
给定一个带权重的有向图G=(V,E),其权重函数为ω:E→R。 在图中,对所有的结点对 u,v∈V,找出从结点u到结点v的最短路径。 该问题的解以表格(二维数组)的形式给出:第u行第v列给出从结点u到结点v的最短路径权重。
约定
1)结点编号:不失一般性,结点编号为1,2,…,|V|。
2)成本邻接矩阵:图G用一个n╳n的邻接矩阵W=(wij)表示, 其中,
3)允许存在权重为负值的边,但不能包含权重为负值的环路,否则无解。
4)最短路径矩阵:算法的输出为一个n╳n的最短路径矩阵 D=(dij),其中dij表示从结点i到结点j的一条 最短路径的权重。算法结束时有dij=δ(i,j)。
5)前驱结点矩阵: 前驱结点矩阵记为:П=(πij),其中
利用前驱结点矩阵П可以计算出每对结点间的最短路径。 前驱结点矩阵П的第i行所诱导的子图是一棵根结点为i的最短路径树。 对于每个结点i∈V,定义图G对于结点i的前驱子图为 Gπ,i=(Vπ,i,Eπ,i),其中
(见CHP24)
打印最短路的过程
动态规划做法
最短路径的最优子结构性质
每条路径都是最短路径:考虑从结点i到结点j的一条最短路径p。假定p至多包含m条边(假定没有权重为负值的环路),且m为有限值。
如果i=j,则p中不包含任何边,所以p的权重等于0;
如果i ≠ j,则将路径p分解为 ,其中 p ’至多包含 m-1 条边,则p ’是从i到k的一条最短路径, 且δ(i,j)=δ(i,k)+Wkj。
递归解
设是从结点i到结点j的至多包含m条边的任意路径中的最小权重。
则
自底向上解
(伪代码在给定W和L(m-1)的情况下计算L(m))
时间复杂度
发现这个计算过程实际上很类似于矩阵乘法(几乎完全一样),可以用矩阵快速幂优化到。
另一种DP——Floyd-Warshall算法
算法允许图中存在负权重的边,但不能存在权重为负值的环路。
思路
假定图G的结点集为V={1,2,…,n}。考虑其中的一个子集 {1,2,…,k},这里k是小于n的某个整数,并是其中的最大编号。 对于任意一对结点i,j∈V,定义p是从i到j、且所有中间结点均取自于集合{1,2,…,k}的最短路径。
p是简单路径,且p的中间结点都不大于k。
p从i 到 j,仅经过集合{1,2,…,k}中的结点,但,
- 不一定经过其中的每一个结点;
- 也可能不存在这样的路径,此时p的权重等于∞。
在从 i 到 j 之间中间结点均取自集合{1,2,…,k-1}的基础上,试图回答这样一个问题:结点k是否是路径p上的一个中间结点?
1)如果结点k不是路径p上的中间结点,则p上的所有中间结点都属于集合{1,2,…,k-1}。 此时,从结点i到结点j的中间结点取自集合{1,2,…,k-1}的一条最短路径也是从结点i到结点j的中间结点取自集合 {1,2,…,k}的一条最短路径。
2)如果结点k是路径p上的中间结点,则k将路径p分解为两段(如下图),最优子结构性,p1是从结点i到结点k的一条最短路径,且中间结点全部取自集合{1,2,…,k-1} 。 因为结点k不是路径p1上的中间结点,所以路径p1上的所有结点都 属于集合{1,2,…,k-1} 。 同理,p2是从结点k到结点j的一条最短路径,且中间结点全部取自集合{1,2,…,k-1}
故有状态转移方程:
伪代码
时间复杂度
加入最短路径构建
为从结点i到结点j的一条所有中间结点都取自集合 {1,2, …, k}的最短路径上j的前驱结点。
应用——计算传递闭包
定有向图G=(V,E),定义图G的传递闭包G*=(V,E*),其中 E*={(i,j):如果图G中包含一条从结点i到结点j的路径}。
求有向图的传递闭包: 方法一:给E中每条边赋权重1,然后运行FLOYD-WARSHALL算法, 可以在Θ(n3)求出权重路径矩阵D。在D中若dij<n,则表示存在一条从结点i到结点j的路径;否则dij=∞。
方法二:定义矩阵T ={tij},若存在一条从结点i到结点j的路径,tij=1,否则tij=0。
计算T:
对FLOYD-WARSHALL算法进行改造:用逻辑或操作(V)和
逻辑与操作(Λ)替换算术操作min和+,得以下计算公式:
用于稀疏图的Johnson算法
Johnson算法:在稀疏图中求每对结点之间的最短路径权重。
对稀疏图,Johnson算法优于Floyd-Warshall算法,时间复杂度可达O(V2lgV+VE)。
Johnson算法使用Dijkstra算法和Bellman-Ford算法作为自己的子程序,可处理带有负权重的图。
如果图中包含所有结点对的最短路径,Johnson算法输出一个包含所有结点对的最短路径权重矩阵;否则报告图中包含权重为负值的环路。
重赋权重:Johnson算法使用重新赋予权重的技术求解。
工作原理
如果图G=(V,E)中所有的边权重ω皆为非负值,则通过对每个结点运行一次Dijkstra算法来找到所有结点对之间的最短路径;
如果图G包含权重为负值的边,但没有权重为负值的环路, 则通过重赋权重,构造出一组新的非负权重值,然后使用上面同样的方法求解。
新赋予的权重函数记为: ,必须满足以下两个重要性质:
1. 路径等价性:对于所有结点对u,v∈V,一条路径p是在使用权重函数ω时的从结点u到结点v的一条最短路径,当且仅当 p是在使用权重时的从u到v的一条最短路径。 即不管是使用原来的权重函数还是新的权重函数,所能求出来的最短路径应是一致的。
2. 非负性:对于所有的边(u, v),新权重为非负值。 即需要经过技术处理,把负权重的边的权重改造成非负值。
引理
(重新赋予权重并不改变最短路径) 给定带权重的有向图G=(V,E),其权重函数为ω:E→R,设h:V→R为任意函数, 该函数将结点映射到实数上。对于每条边(u,v)∈E,定义
设 为从结点v0到结点vk的任意一条路径,那么,p是在使用权重函数ω时从结点v0到结点vk的一条最短路径, 当且仅当p是在使用权重函数时从结点v0到结点vk的一条最短路径,即: ω(p)=δ(v0 ,vk ) 当且仅当 。 而且,图G在使用权重函数ω时不包含权重为负值的环路, 当且仅当p在使用权重函数也不包含权重为负值的环路。
剩下的问题就是如何找到使非负的 h 函数
对于图G构造一幅新图G’ =(V’ , E’),其中 V’ =V∪{s},s是一个新结点, , 并令,对于所有结点v∈V,有ω(s,v)=0。 由于结点s没有入边,所以除了以s为源点的最短路径外,图G’ 中没 有其它包含s的最短路径。而且G'不包含权重为负值的环路当且仅当图G不包含权重为负值的环路。
假定图G和图G’都不包含权重为负值的环路。 对于所有的结点v∈V’ ,定义:h(v)=δ(s,v)。 根据三角不等式,对于所有的边(u,v)∈E’ ,有 h(v)≤h(u)+ω(u,v)。 定义新权重 ,有
即满足要求。
伪代码
先用Bellman-Ford算法计算s到各个结点的最短路径,并判断是否存在负权重的环路。
再利用Bellman-Ford算法计算得到的δ(s,v)定义h(v)的值,并重新赋边的权重。
然后对每个点跑一遍Dijkstra算法。
时间分析
算法的运行时间依赖于Dijkstra算法中最小优先队列的实现方式:
如果使用斐波那契堆实现,则Johnson算法的运行时间为 。
如果使用二叉最小堆实现,则Johnson算法的运行时间为 O(VElgV)。
在稀疏图的情况下,该算法的时间比Floyd-Warshall算法 的表现()要好。