您的位置:首页 > 其它

算法导论 - 第25章 每对顶点间的最短路径

2011-12-16 22:50 232 查看
每对顶点间的最短路径的算法有三种,每一种都可以检测图是否存在weighg小于0的cycle。

前两种算法用了动态规划的方法,最后一种算法对每个定点计算单源最短路径。

与求单源最短路径的算法不同,求每对顶点间的最短路径的算法采用网的矩阵表示法(除了最后一种算法,最后一种算法采用图的邻接表表示法)。用矩阵W表示一个网,其中矩阵的元素W(i,j)表示顶点i到顶点j的edge的weight。如果顶点i到顶点j之间没有edge,则W(i,j)等于无穷大。W(i,i)等于0。

用n表示图中顶点的个数。

算法1:

用矩阵L(m)来表示每对顶点间的最短路径的weight,每对顶点之间的最短路径最多只有m条edge。

L(1)=W

L(m)(i,j) = min{L(m-1)(i,k) + W(k,j)};k=[1,n]

由于最短路径的长度(指edge的个数,不是只路径的weight)必然小于等于n-1,所以L(n-1)就是我们所需要求的。

L(1) ---> L(2) ---> L(3) ---> L(4) ---> ... ---> L(n-1)

该方法的时间复杂度为O(n^4)。

计算过程中,如果某个矩阵的对角线元素小于0,(对角线元素只能等于0或小于0),说明网中存在weight小于0的cycle。

算法2:

算法2的名字叫Floyd-Warshall Algorithm。该方法也是采用动态规划的方法。思路与算法1差不多。

用矩阵D(m)来表示每对顶点间的最短路径的weight,每对顶点之间的最短路径的中间结点(也就是最短路径中去掉source和destination后剩下的所有顶点)的编号最大为m。

D(0)=W (表示没有中间结点)

D(1)(i,j)=min{D(0)(i,1)+D(0)(1,j)}

D(m)(i,j)=min{D(m-1)(i,m)+D(m-1)(m,j)}

D(n)就是我们需要求的。

D(0) ---> D(1) ---> D(2) ---> D(3) ---> D(n)

算法复杂度为O(n^3)

计算过程中,如果某个矩阵的对角线元素小于0,(对角线元素只能等于0或小于0),说明网中存在weight小于0的cycle。

算法3:

算法3的名字叫Johnson's algorithm。该算法对每个顶点计算单源最短路径。单源最短路径的算法包括Bellman-Ford算法和Dijkstra算法。

如果对每个顶点采用Bellman-Ford算法,那就没什么事情。Bellman-Ford算法本身可以检测是否存在weight小于0的cycle。但Bellman-Ford的时间复杂度比Dijkstra算法没有优势,因此Johnson's algorithm是对每个顶点采用Dijkstra算法。由于Dijkstra算法的要求是网中不能存在weight小于0的edge。因此需要采取一些办法来解决这个问题。

Johnson's algorithm通过对每条edge重新赋予weight来保证每条edge的weight大于等于0。用W(u,v)表示顶点u到顶点v的weight,如果edge(u,v)不存在,则W(u,v)为无穷大。用W’(u,v)来表示新的weight。用D(i,j)来表示原来weight条件下,顶点i到顶点j之间的最短路径的weight,用D'(i,j)表示用W‘时,顶点i到顶点j之间最短路径的weight。G=(V,E,W), G' = (V,E,W')。

则显然,我们特地生成出个G’,肯定是要满足一定条件的。这些条件就是:

1 在G中,设p为顶点i到顶点j之间的最短路径,则p也必须是在G’中,顶点i到顶点j之间的最短路径。反之亦然。

2 显然,W‘(i,j)必须都大于等于0。

那么怎么生成W',使得G’满足以上两个条件呢?

假设对每个顶点映射一个值,用函数h来表示,即h(u)是某个数,u是图G中的任何一个顶点。

让W'(i,j) = W(i,j)+h(i)-h(j)

则不管h这个映射如何实现,用该方法产生的G‘满足条件1。

设p(i,j)是G中任何一对顶点的任一条路径的weight,p'(i,j)是该路径在G’中的weight。则有关系:p'(i,j) = p(i,j)+h(i)-h(j)

那如何构造h,使得G'满足条件2?

在G’中增加一个顶点s,增加n条edge:(s,v1),(s,v2)....(s,vn)。每条边的weight为0。

我们看看新构造的G‘。由于顶点s没有入边,所以v1,v2,v3...vn之间的任何最短路径都不会经过s。所以v1,v2,v3...vn中每对顶点的最短路径,最短路径的weight都保持不变。

以顶点s作为source,用Bellman-Ford算法求单源最短路径。求得d1,d2,d3...dn。显然,di必然小于等于0。

我们采用映射h(u)=du来计算W’,就可以使得G‘满足条件2。

证明:对edge(v,u),有du <= dv+W(v,u)。也就是h(u) <= h(v)+W(v,u),把v换成i,把u换成j,就是h(j) <= h(i)+W(i,j),即h(i)-h(j)>=-W(i,j)。

W'(i,j) = W(i,j)+h(i)-h(j)>=W(i,j) + (-W(i,j)) = 0。

Done!!

Johnson's algorithm伪代码如下所示:

1 构造G’

2 以顶点s为source,用Bellman-Ford算法求单源最短路径。如果存在weight小于0的cycle,返回。

3 计算W'(i,j) = W(i,j)+h(i)-h(j)。

4 对G‘中每个顶点(s除外)调用Dijkstra方法,每对顶点的最短路径的weight保存在矩阵D'(i,j)中。

5 D(i,j) = D'(i,j)+h(j)-h(i).
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐