Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 40

Floyd-Warshall Algorithm for All-Pairs Shortest Paths

Recommended resources

Hello! In our last lesson, we explored topological sorting, a method for ordering vertices in a Directed Acyclic Graph. We'll now continue our journey into advanced graph algorithms by tackling a different, but equally important, problem.

This lesson focuses on the All-Pairs Shortest Path (APSP) problem. While algorithms like Dijkstra's and Bellman-Ford are excellent for finding the shortest paths from a single source, the APSP problem aims to find the shortest path between every possible pair of vertices in a graph. Our goal is to understand and apply the Floyd-Warshall algorithm, a classic and elegant dynamic programming solution to this problem. This topic is a great intersection of graph theory and the dynamic programming concepts you're interested in.

1. The All-Pairs Shortest Path Problem

Imagine you're designing a routing system for a small, dense network or calculating travel times between all cities on a map. In these scenarios, you need to know the shortest path not just from one starting point, but from any point to any other.

A straightforward way to solve this would be to run a single-source shortest path (SSSP) algorithm from each vertex. If your graph has no negative-weight edges, you could run Dijkstra's algorithm times, where is the number of vertices. For a dense graph where the number of edges is close to , this would result in a complexity around using a simple implementation of Dijkstra's. If there are negative edges, you would need to use Bellman-Ford, leading to a complexity of .

The Floyd-Warshall algorithm provides an alternative, exceptionally clear method that achieves complexity and is particularly well-suited for graphs represented by an adjacency matrix. It elegantly handles both positive and negative edge weights (but not negative-weight cycles).

Let's start with a high-level overview of the algorithm and where it fits in the landscape of shortest path algorithms.

Floyd Warshall All Pairs Shortest Path Algorithm | Graph Theory | Dynamic Programming

This video from WilliamFiset introduces the Floyd-Warshall algorithm, explains its purpose, and provides a useful table comparing it to other shortest path algorithms like BFS and Dijkstra's.

Watch the first 1 minute and 52 seconds of the video. Pay attention to the comparison table, which highlights that Floyd-Warshall shines on small graphs and when solving the all-pairs problem.


2. The Core Idea: Dynamic Programming with Intermediate Vertices

The brilliance of the Floyd-Warshall algorithm lies in its dynamic programming structure. Instead of building paths edge by edge, it considers which intermediate vertices a path is allowed to use.

Let's number the vertices from 1 to . The algorithm proceeds in phases. In phase , we calculate the shortest paths between all pairs of vertices that are allowed to use any of the vertices in the set as intermediate stops.

Let be the length of the shortest path from vertex to vertex using only intermediate vertices from the set .

  • Base Case (): Before we allow any intermediate vertices, the only paths available are direct edges. So, is simply the weight of the edge from to if one exists, if there is no direct edge, and 0 if . This is our initial adjacency matrix.

  • Recursive Step: Now, to compute , we consider paths from to that can use intermediate vertices from . There are two possibilities for the shortest such path:

    1. It does not use vertex . In this case, the path only uses intermediate vertices from , so its length is .
    2. It does use vertex . This path can be broken into two parts: a path from to and a path from to . Since both of these sub-paths can only use intermediate vertices from the set , their combined length is .

We take the minimum of these two cases. This gives us the core recurrence relation:

After phases, will hold the shortest path from to using any of the graph's vertices as intermediates—which is the final answer.

The following reading offers a clear, formal description of this process.

Floyd-Warshall - finding all shortest paths

The article from CP-Algorithms provides a concise, text-based explanation of the algorithm's dynamic programming foundation.

Read the sections titled "Description of the algorithm" and the following short, unnamed section that presents the recurrence relation. Focus on how the problem is broken down into phases based on the allowed set of intermediate vertices.

To see this recurrence in action, let's watch a step-by-step example.

4.2 All Pairs Shortest Path (Floyd-Warshall) - Dynamic Programming

This video by Abdul Bari provides an excellent, manual walkthrough of the first few iterations of the algorithm, showing how the distance matrix is updated. This will help make the abstract formula more concrete.

Watch from 02:25 to 08:53. Observe how he constructs the matrix for k=1 by considering vertex 1 as an intermediate, and then uses that result to construct the matrix for k=2.

The image below shows the full evolution of the distance matrix for a 4-node graph. Notice how in each step , the algorithm considers paths that go through vertex (highlighted row and column) and updates the distances (circled in red) if a shorter path is found.

Floyd-Warshall Algorithm Iteration Example
A step-by-step demonstration of the Floyd-Warshall algorithm. The matrix `d^(k)` represents the shortest path distances after considering intermediate vertices up to `k`. At each step, new shorter paths found by going through vertex `k` are circled.

3. Implementation, Complexity, and Negative Cycles

The algorithm's implementation is remarkably straightforward, consisting of three nested loops.

for (k = 0; k < V; ++k) {
    for (i = 0; i < V; ++i) {
        for (j = 0; j < V; ++j) {
            // If path through k is shorter
            if (dist[i][k] + dist[k][j] < dist[i][j]) {
                dist[i][j] = dist[i][k] + dist[k][j];
            }
        }
    }
}

A crucial detail is that the outermost loop must be k. This ensures that when we are in phase k, the shortest paths using intermediate vertices {1, ..., k-1} have already been computed.

Space Optimization

You might notice that the recurrence suggests we need a 3D array (or two 2D arrays for the current and previous states). However, the algorithm works correctly even if we update the 2D distance matrix in place. This is because, during iteration k, the values dist[i][k] and dist[k][j] are not changed. Their shortest paths, by definition, do not use k as an intermediate vertex. Therefore, we can safely use their (k-1)-state values to update dist[i][j] for the k-th state.

Complexity

  • Time Complexity: due to the three nested loops, each running times.
  • Space Complexity: to store the adjacency/distance matrix.

Handling Negative Weights and Cycles

The Floyd-Warshall algorithm correctly handles negative edge weights. However, if the graph contains a negative-weight cycle, the concept of a shortest path is ill-defined (you could traverse the cycle infinitely to get an arbitrarily small path cost).

The algorithm can be used to detect such cycles. After the algorithm has run, if the distance from any vertex to itself, dist[i][i], is negative, it implies that there is a negative-weight cycle reachable from vertex i.

This video provides a great walkthrough of the pseudocode and discusses the handling of negative cycles.

Floyd Warshall All Pairs Shortest Path Algorithm | Graph Theory | Dynamic Programming

Let's look at the implementation details, including the setup, the main loops, and how to detect negative cycles.

Watch from 07:32 to 14:12. The first part covers the pseudocode and space optimization. The second part explains what negative cycles are and how Floyd-Warshall can be used to detect their presence and impact.

Floyd-Warshall Shortest Paths Example
An example showing an input graph with negative weights, its initial weight matrix, and the final shortest path distances computed by the Floyd-Warshall algorithm.

4. Reconstructing the Shortest Path

The algorithm as presented computes the lengths of the shortest paths. To reconstruct the actual paths, we need to store more information. A common technique is to use a successor matrix, next[i][j], which stores the first vertex on the shortest path from i to j.

Initially, if there's an edge from i to j, we set next[i][j] = j.

Then, inside the main loop, when we update the distance dist[i][j] because a shorter path through k is found, we also update the successor:
next[i][j] = next[i][k]

This means the first step on the path from i to j is the same as the first step on the path from i to k. By following these next pointers, we can reconstruct the full path.

The final segment of the Fiset video explains this reconstruction process.

Floyd Warshall All Pairs Shortest Path Algorithm | Graph Theory | Dynamic Programming

Finally, let's see how to reconstruct the actual sequence of vertices in a shortest path using an auxiliary 'next' matrix.

Watch from 14:12 to the end. This section shows how to build and use the 'next' matrix to trace a path from a start to an end node.


Conclusion

In this lesson, you've learned the Floyd-Warshall algorithm, a powerful method for solving the all-pairs shortest path problem. Its clean, dynamic programming structure makes it both effective and conceptually elegant.

Key Takeaways:

  • The Floyd-Warshall algorithm finds the shortest paths between all pairs of vertices in a weighted directed graph.
  • It has a time complexity of and is well-suited for dense graphs represented by an adjacency matrix.
  • Its core DP strategy involves iteratively relaxing path constraints by allowing an increasing set of intermediate vertices. The recurrence is .
  • The algorithm handles negative edge weights and can be used to detect the presence of negative-weight cycles by checking if dist[i][i] < 0 for any vertex i.
  • An auxiliary successor matrix can be maintained to reconstruct the actual shortest paths.

Preview of the Next Lesson:
We will now synthesize concepts from our last two lessons. In the next session, we will explore how to formulate and solve Dynamic Programming problems on Directed Acyclic Graphs (DAGs). This involves processing the vertices in a topological order, which you learned about previously, to solve DP problems efficiently on graph structures.