Floyd算法

Floyd算法是求任意图中任意两个节点的最短路径的算法,一般认为Floyd算法使用了动态规划策略。即对任意一条最短路径u ~v, 假如k在该路径中,则改最短路径可以表示为u ~k~v。

 

Di,j,k为从ij的只以(1..k)集合中的节点为中间节点的最短路径的长度。

  1. 若最短路径经过点k,则Di,j,k = Di,k,k − 1 + Dk,j,k − 1
  2. 若最短路径不经过点k,则Di,j,k = Di,j,k − 1

因此,Di,j,k = min(Di,k,k − 1 + Dk,j,k − 1Di,j,k − 1)。


在实际算法中,为了节约空间,可以直接在原来空间上进行迭代, 并且Di,j,k 是肯定会比Di,k,k − 1 小的,所以算法伪代码如下

  for(k = 1; k <= D.size; ++k)

    for(i = 1; i <= D.size; ++i)

      for(j = 1; j <= D.size; ++j)

        D[i][j] = D[i][j] < D[i][k] + D[k][j]  ? D[i][j] : D[i][k] + D[k][j]

 

换一种思路理解,每次最外层循环,都把所有从k节点出发的边进行了一次松弛操作。假设存在这样一条最短路径  u -> k+2 -> k+1 -> v,那么在对k+1层循环时k+2 -> k+1 -> k的最短路径被确定, 然后在k+2次循环时,u -> k+2 -> k+1 -> v的最短路径被确定,结合松弛操作的性质,一旦某跳最短路径的估计权重被缩小到实际的最短路径权重,它的值将不会改变,所以最后求到的路径就一定是最短路径。

 

vector<vector<int>> floyd(vector<vector<int>> &g){

    vector<vector<int>> sp(g.size(), vector<int>(g[0].size()));

    for(int i = 0; i < g.size(); ++i) {

        for(int j = 0; j < g.size(); ++j) {

            sp[i][j] = g[i][j];

        }

    }

    for(int k = 0; k < g.size(); ++k) {

        for(int i = 0; i < g.size(); ++i) {

            for(int j = 0; j < g.size(); ++j) {

                sp[i][j] = sp[i][j] > sp[i][k] + sp[k][j] ? sp[i][k] + sp[k][j] : sp[i][j];

            }

        }

    }

    return sp;

}

 

 

 

posted on 2015-07-03 20:21  远近闻名的学渣  阅读(300)  评论(0)    收藏  举报

导航