Bellman-Ford and Dijkstra's algorithms provide a means to find the shortest path from a given source. However often we may wish to find the shortest paths between all pairs of vertices. One way to accomplish this would be to simply run Bellman-Ford or Dijkstra's algorithm for each vertex in the graph. Thus the run times for these strategies would be (particularly for dense graphs where |E| ≈ |V|2):

Bellman-Ford - |V| O(VE) ≈ O(V4)

Dijkstra - |V| O(V2 + E) ≈ O(V3)

|V| O(V lg V + E) ≈ O(V2 lg V + VE)

In the case of dense graphs an often more efficient algorithm (with very low hidden constants) for finding all pairs shortest paths is the Floyd-Warshall algorithm.

Floyd-Warshall Algorithm

The Floyd-Warshall algorithm works based on a property of intermediate vertices of a shortest path. An intermediate vertex for a path p = <v1, v2, ..., vj> is any vertex other than v1 or vj.

If the vertices of a graph G are indexed by {1, 2, ..., n}, then consider a subset of vertices {1, 2, ..., k}. Assume p is a minimum weight path from vertex i to vertex j whose intermediate vertices are drawn from the subset {1, 2, ..., k}. If we consider vertex k on the path then either:

k is not an intermediate vertex of p (i.e. is not used in the minimum weight path)

⇒ all intermediate vertices are in {1, 2, ..., k-1}

k is an intermediate vertex of p (i.e. is used in the minimum weight path)

⇒ we can divide p at k giving two subpaths p1 and p2 giving vikvj

⇒ by Lemma 24.1 (subpaths of shortest paths are also shortest paths) subpaths p1 and p2 are shortest paths with intermediate vertices in {1, 2, ..., k-1}

Thus if we define a quantity d(k)ij as the minimum weight of the path from vertex i to vertex j with intermediate vertices drawn from the set {1, 2, ..., k} the above properties give the following recursive solution

image

Thus we can represent the optimal values (when k = n) in a matrix as

image

Algorithm

Basically the algorithm works by repeatedly exploring paths between every pair using each vertex as an intermediate vertex.

    FLOYD-WARSHALL(W)
    1.  n = W.rows
    2.  D(0) = W
    3.  Π(0) = π(0)ij = NIL if i = j or wij = ∞
                     = i   if i ≠ j and wij < ∞
    4.  for k = 1 to n
    5.     let D(k) = (d(k)ij) be a new n x n matrix
    6.     for i = 1 to n
    7.        for j = 1 to n
    8.           dkij = min(d(k-1)ij, d(k-1)ik + d(k-1)kj)
    9.           if d(k-1)ij ≤ d(k-1)ik + d(k-1)kj
    10.             π(k)ij = π(k-1)ij
    11.          else
    12.             π(k)ij = π(k-1)kj
    13. return D(n)

Since Floyd-Warshall is simply three (tight) nested loops, the run time is clearly O(V3).

Example

Using the same directed graph from lecture 22 and lecture 23

image

Initialization: (k = 0)

image

Iteration 1: (k = 1) Shorter paths from 2 ↝ 3 and 2 ↝ 4 are found through vertex 1

image

Iteration 2: (k = 2) Shorter paths from 4 ↝ 1, 5 ↝ 1, and 5 ↝ 3 are found through vertex 2

image

Iteration 3: (k = 3) No shorter paths are found through vertex 3

image

Iteration 4: (k = 4) Shorter paths from 1 ↝ 2, 1 ↝ 3, 2 ↝ 3, 3 ↝ 1, 3 ↝ 2, 5 ↝ 1, 5 ↝ 2, 5 ↝ 3, and 5 ↝ 4 are found through vertex 4

image

Iteration 5: (k = 5) No shorter paths are found through vertex 5

image

The final shortest paths for all pairs is given by

image

Transitive Closure

Floyd-Warshall can be used to determine whether or not a graph has transitive closure, i.e. whether or not there are paths between all vertices.

This procedure can implement a slightly more efficient algorithm through the use of logical operators rather than min() and +.

Johnson's Algorithm

While Floyd-Warshall is efficient for dense graphs, if the graph is sparse then an alternative all pairs shortest path strategy known as Johnson's algorithm can be used. This algorithm basically uses Bellman-Ford to detect any negative weight cycles and then employs the technique of reweighting the edges to allow Dijkstra's algorithm to find the shortest paths. This algorithm can be made to run in O(V2 lg V + VE).