任意两点最短路径问题

问题描述

       输入:图G = (V,E)

       输出:图中任意两点的最短路径

算法描述(Floyd算法)

     1. 分析优化子结构

       定理1,Vi,Vj的最短路径包含两点Vm,Vn,那么Vi,Vj的最短路径中对应Vm,Vn的部分一定是Vm,Vn在该图中的一条最短路径。

       证明1,可以通过反证法进行证明,如果不是,那么可以构造出比当前Vi,Vj的最短路径更短的路径。

     2. 分析子问题重叠性。

       首先,需要了解Vi,Vj的递归代价方程。

       定义:D(i,j)为Vi,Vj的最短路径长度。

  • D(i,j) = 0,if i = j.
  • D(i,j) = min ( D(i,j) , D(i,k) + D(k,j)),其中,i ≤ k ≤ j,if i ≠ j.

       那么此问题的计算形式基本上于矩阵链乘问题的计算形式,这就是一个划分动态规划,那么同理自然就有子问题重叠性。

     3.递归地定义最优解的代价 

  • D(i,j) = 0,if i = j.
  • D(i,j) = min ( D(i,j) , D(i,k) + D(k,j)),其中,i ≤ k ≤ j,if i ≠ j.

     4.自底向上地计算优化解的代价保存之,并获取构造最优解的信息

       对于该算法而言,计算顺序是值得思考的。如果直接进行遍历计算,可能当计算D(i,j)时,所使用的D(i,k)以及D(k,j)都并非是最小代价,可以说,每个D(i,j)都相互影响。

       解决办法为:构建顶点集合S以及表示任意两点之间最小路径代价的二维矩阵M,

  • 初始时,S为空,M中仅仅将边录入,无边记为无穷。
  • 依次向S中加入顶点,并仅仅将该顶点作为递归方程中的顶点Vk,更新M。
  • 当S = V时,M中记为最短路径代价。

      故而可以设计算法为:

Floyd算法
D <-- W
P <-- 0
For k = 1 to n Do /*k控制填入元素*/
     For i = 1 to n Do /*i,j控制矩阵的遍历*/
        for j = 1 to n
           if (D[ i, j ] > D[ i, k ] + D[ k, j ] )
           then D[ i, j ] = D[ i, k ] + D[ k, j ]
                   P[ i, j ] = k; 

     5.根据构造最优解的信息构造优化解

        注意,下列算法只打印中间节点,而不会答应起止节点,所以,P中无边或者直接有边的值均为0.

path(index q, r)
     if (P[ q, r ]!=0)
         path(q, P[q, r])
         println( “v”+ P[q, r])
         path(P[q, r], r)
         return;
     //no intermediate nodes
     else return 

  6.算法复杂性分析:

       时间复杂性:

           计算代价的时间复杂性:O(n^3)。

           构造最优解时间复杂性:O(n)。最多只会遍历n个顶点

           空间复杂性:O(n^2)。

 

posted @ 2020-08-28 16:27  zqybegin  阅读(784)  评论(0编辑  收藏  举报