Loading

图最短路径之Floyd

 

Floyd Warshall Algorithm

算法参考地址:Floyd Warshall Algorithm | DP-16 - GeeksforGeeks

算法的简介

Floyd 用于求解所有对最短路径问题。问题在于在给定边加权(可以是负权边)有向图中查找每对顶点之间的最短距离。

时间复杂度: O(V^3)

空间复杂度: O(V^2)

例:

Input:
      graph[][] = { {0,   5, INF, 10},
                  {INF, 0, 3, INF},
                  {INF, INF, 0,   1},
                  {INF, INF, INF, 0} }
which represents the following graph
            10
      (0)------->(3)
      |         /|\
    5 |         |
      |         | 1
      \|/         |
      (1)------->(2)
          3      
Note that the value of graph[i][j] is 0 if i is equal to j
And graph[i][j] is INF (infinite) if there is no edge from vertex i to j.

Output:
Shortest distance matrix
    0     5     8     9
  INF     0     3     4
  INF   INF     0     1
  INF   INF   INF     0

算法的过程

Floyd 算法 我们初始化与输入图矩阵相同的解矩阵作为第一步。然后,我们通过将所有顶点视为中间顶点来更新解矩阵。这个想法是逐个选择所有顶点并更新所有最短路径,其中包括选择的顶点作为最短路径中的中间顶点。当我们选择顶点数 k 作为中间顶点时,我们已经将顶点 {0, 1, 2, .. k-1} 视为中间顶点。对于源顶点和目标顶点的每对 (i, j),有两种可能的情况。 1) k 不是从 i 到 j 的最短路径中的中间顶点。我们保持 disti 的值不变。 2) k 是从 i 到 j 的最短路径中的中间顶点。我们将 disti 的值更新为 disti + distk 如果 disti > disti + distk 下图显示了所有对最短路径问题中的上述最优子结构属性。

弗洛伊德·沃歇尔算法

算法的实现

golang

// F 代表两点之间不可达
const F = 10000
func floyd(graph [][]int) [][]int {
  n := len(graph)
  dist := make([][]int, n)
  for i := 0; i < n; i++ {
     dist[i] = make([]int, n)
  }
  copy(dist, graph)
  for k := 0; k < n; k++ {
     for i := 0; i < n; i++ {
        for j := 0; j < n; j++ {
           if dist[i][k]+dist[k][j] < dist[i][j] {
              dist[i][j] = dist[i][k] + dist[k][j]
          }
        }
    }
  }
  return dist
}

Java

class Floyd {
   private final static int VERTEX = 7;
   private final static int[][] MATRIX = new int[VERTEX][VERTEX];
   private final static int MAX_VALUE = 100000;

   /**
    * 初始化邻接矩阵
    */
   static void initMatrix() {
       for (int i = 0; i < VERTEX; i++) {
           for (int j = 0; j < VERTEX; j++) {
               MATRIX[i][j] = MAX_VALUE;
          }
      }
  }

   /**
    * 初始化边
    */
   static void initEdge() {
       MATRIX[0][1] = 6;
       MATRIX[0][3] = 2;
       MATRIX[1][2] = 5;
       MATRIX[1][5] = 3;
       MATRIX[3][4] = 5;
       MATRIX[3][1] = 7;
       MATRIX[4][6] = 1;
       MATRIX[5][4] = 2;
       MATRIX[5][2] = 3;
  }

   private static void floyd(int[][] matrix) {
       for (int m = 0; m < matrix.length; m++) {
           for (int i = 0; i < matrix.length; i++) {
               for (int j = 0; j < matrix.length; j++) {
                   if (matrix[i][m] + matrix[m][j] < matrix[i][j]) {
                       matrix[i][j] = matrix[i][m] + matrix[m][j];
                  }
              }
          }
      }
  }

   public static void main(String[] args) {
       initMatrix();
       initEdge();
       //调用算法计算最短路径
       floyd(MATRIX);
  }

}

 

posted @ 2021-08-29 15:40  Philosophy  阅读(413)  评论(0编辑  收藏  举报