代码改变世界

算法导论-单源最短路径习题解

2012-04-11 09:32  meteorgan  阅读(2603)  评论(0编辑  收藏  举报

24.1-5 设G=(V,E)为一带权有向图,其权函数w: E->R。请给出一个O(VE)时间的算法,对于每个顶点v 属于V,找出值δ*(v) = min{δ(u,v)},u属于V。

  解: 1. 对每个顶点,令d[v] = 0。(初始情况,如果没有负权边,则δ*(v) = 0)

     2. 用Bellman-ford算法,计算d[v],得d[v] = δ*(v)。

    简单证明:设δi(u,v)为从u到v边个数不超过i的路径的最小值。δ*i (v) = min{δi(u,v)},u属于V。则有δ*(v) = δ*n-1(v)。可以数学归纳法证明d[v] <= δ*i(v)。显然d[v] <= δ*0(v) = 0。

              假设在Bellman-ford 算法前i次迭代中 d[v] <= δ*i(v) 成立,u为所有与v相邻的顶点。对第i+1次迭代,如果δ*i+1(v) = δ*i(v),则d[v] <= δ*i(v)恒成立,否则在此轮中边[u,v]被松弛,所以有d[v] = min{d[u] + w[u,v]} <= min{δ*i(u) + w[u,v]} = δ*i+1(v)。 所以有d[v] <= δ*n-1(v),又d[v]为两顶点间路径长,所以有d[v] = δ*n-1(v)。 

 

  24.1-6 假定一加权有向图G=(V,E) 包含一负权回路。请给出一个能够列出此回路上的顶点的高效算法,并证明你的算法的正确性。

  解:Bellman-ford 算法,如果发现d[v] > d[u] + w[u,v],则点u,v处于一个负权回路中,此时可以通过寻找前驱顶点得到负权回路。时间复杂度O(VE)。

 

24.2-4 给出一个高效算法来统计有向无回路图中的全部路径数。分析所给出的算法。

  解: 对图进行拓朴排序,然后按照拓朴排序的逆顺序计算N[u],其中N[u] = sum{N[v]}, [u,v]是所有以u为出发点的边。然后计算sum{N[u]}, u属于V。时间复杂度O(V+E)。

 

24.4-5 试说明如何对Bellman-Ford算法做稍作修改,使其在解决关于n个未知量的m个不等式所定义的差分约束系统时,运行时间为O(nm)。

  解:在约束图中,顶点v0的入度为0,即d[v0]不会发生变化,因此d[v0] + w[v0, v]也不会变化。在运行Bellman-Ford算法时,不用对边[v0, v]进行松弛。 另外一种方法是不用引入顶点v0及相应的边[v0, v],直接对个顶点令d[v] = 0(题24.4-7)。

 

 24-2 嵌套框

  解:a) 略

    b) 对两个嵌套框进行排序,时间O(dlgd),如果(x1, x2, ……xd)可以嵌套在(y1, y2,……yd),则有x< yi 。比较可以在O(d)时间内完成。总时间为O(dlgd)

    c) 构造一个图G=(V,E),顶点为所有的B,如果B可以嵌套在B中,则有边(Bi, Bj)。显然图G是有向无回路图,则可以在O(V+E)时间内找到最长路径。由于|E| < |V|2  ,总的时间复杂度为O(ndlgd + dn2)

 

 24-2 套汇问题

  解: a) 此问题可转化为图问题。构造一个图G=(V,E),其中顶点为ci,任意两点间都有两条有向边(vi, vj), (vj, vi)。则有|V| = n, |E| = n(n-1)/2。从题目条件可得:

                    

                   因此可设边(ci1,ci2) 权值为-lgR[i1, i2] ,这样问题转化为在图中寻找负权回路的问题。可以现在图中添加一个新的顶点s, s指向所有入度为0的顶点,权值为0;然后以s为起点运行Bellman-Ford 算法,即可确定是否有负权回路。时间复杂度为O(n3)

         b) 寻找负权回路的所有顶点,题24.1-5。

 

24-3 关于单源最短路径的Gabow定标算法

  解: a) 由于可能有回路,不能按照拓扑排序的顺序松弛,Bellman-Ford算法难以达到O(E)的时间复杂度。因此使用Dijkstra算法,但要采用较为复杂的数据结构。由于δ(s,v) <= |E|,初始化时,将d[v] 设为|E| + 1,用数组Q[0, ...|E|+1]实现最小优先级队列,每个元素为一个链表,链表Q[i]中所有元素的d值为i。然后设c为当前非空的最小链表的位置。这样可以在O(1)时间内执行EXTRACT-MIN(Q),|E|次EXTRACT-MIN(Q) 操作可以在O(|E|)时间内完成;对于DECREASE-KEY操作,每当减小d[v]时,将顶点v移动到链表Q[d[v]]的第一个位置,这样一次DECREASE-KEY可以在O(1)时间内完成,|E|次DECREASE-KEYKE可以在O(|E|)时间内完成。总的时间复杂度为O(|E|)。

    b) 由于w1(u,v)要么为1,要么为0,所以有δ1(s,v) <= |E|,所以可以在O(|E|)时间内计算δ1(s,v)。

    c) wi = w >> 2k-i, wi-1 = w >> 2k+1-i ,所以有wi(u,v) = 2wi-1(u,v)或 2wi-1(u,v)+1。如果δi(s,v)路径和δi-1(s,v)路径相同则有 δi-1(s,v) <= δi(s,v),如果路径不同,则必有 δi-1(s,v) < δi(s,v)。路径δi(s,v)最大边数为|V|-1,所以有δi(s,v) <= δi-1(s,v) + |V|-1。

    d) 有三角不等式得:δi-1(s,v) <= δi-1(s,u) + wi-1(u,v),所以2δi-1(s,u) - 2δi-1(s,v) <= -2wi-1(u,v)。所以有wi(u,v) + 2δi-1(s,u) - 2δi-1(s,v) >= 0,又对任意的i有wi (u,v)是整数,所以

 ˆwi(u,v)为非负整数。

    e) 由引理25-1:重赋权不会改变最短路径知,ˆδ(s,v)和δ(s,v)的路径相同。ˆδi(s,v) = Σˆwi(u,v) ,累加即可得出结论。

    f) 题目中已经证明了……

 

24-6 双调最短路径

  解:双调序列最多出现两次变化,即双调序列的形式为:一直递增;一直递减;递增,递减,递增;递减,递增,递减。由于单源最短路径都是双调序列,如果按照双调序列的顺序做releax,就能找到最短路径。所以可以做四遍releax操作,1、3这两次按照权值递增的顺序做releax;2、4按权值递减的顺序做releax,然后就可以得到最短路径。时间复杂度:排序需要O(|E|lg|E|),四遍releax操作需要O(|E|)时间,初始化时间为O(|V|),总时间为O(|E|lg|E| + |V|)。