1. Home
  2. Design & Analysis of Algorithms
  3. Floyd–Warshall (All-Pairs Shortest Paths)

Floyd–Warshall (All-Pairs Shortest Paths)

Find the shortest distance between every pair of nodes with three simple loops. Watch the distance matrix improve as each node becomes an allowed stop-over.

Interactive 3DIntermediate12 min readDAAUpdated

Drag to rotate · Right-drag to pan · Click, then scroll to zoom · Space play · ←→ step

What's happening

Pseudocode

    Try this in the 3D model

    • Watch the cell B → D. It starts at ∞ and improves twice. Through which stop-overs?
    • After k = A, look at the cyan row and column — why do they never change during that round?
    • Try a Random directed graph and predict which ∞ cells will disappear.

    The problem

    Dijkstra’s algorithm finds shortest paths from one source. But sometimes you need the distance between every pair of places — think of the distance table printed in a road atlas. That’s the all-pairs shortest path problem.

    Floyd–Warshall solves it with a beautifully short algorithm.

    The idea: allow one more stop-over at a time

    Number the vertices 1..V. Define:

    dist[i][j] after round k = the shortest path from i to j that is allowed to pass only through vertices 1..k as stop-overs.

    • Before any rounds, only direct edges are allowed (∞ if there is none).
    • In round k, a path from i to j can either avoid k (keep the old value) or go through k:
    dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j])

    After the last round, every vertex is allowed as a stop-over, so dist holds the true shortest distances.

    In the 3D model, the current stop-over k glows pink, the row and column of k (the values being used) are cyan, and each improved cell flashes yellow.

    Walk-through

    Take the cell B → D in the sample graph. With only direct edges it’s ∞ (there is no edge B → D).

    • k = A: B → A → D = 8 + 7 = 15 → improved to 15.
    • k = C: B → C → D = 2 + 1 = 3 → improved to 3.

    Every other cell improves in the same way.

    Code

    INF = float('inf')
    
    def floyd_warshall(dist):
        """dist: V x V matrix with 0 on the diagonal and INF for missing edges (modified in place)"""
        V = len(dist)
        for k in range(V):
            for i in range(V):
                for j in range(V):
                    if dist[i][k] + dist[k][j] < dist[i][j]:
                        dist[i][j] = dist[i][k] + dist[k][j]
        return dist
    
    # The sample graph from the 3D model (A, B, C, D = 0..3)
    d = [[0,   3,   INF, 7],
         [8,   0,   2,   INF],
         [5,   INF, 0,   1],
         [2,   INF, INF, 0]]
    for row in floyd_warshall(d):
        print(row)
    # [0, 3, 5, 6]
    # [5, 0, 2, 3]
    # [3, 6, 0, 1]
    # [2, 5, 7, 0]
    #include <iostream>
    #include <vector>
    using namespace std;
    const int INF = 1e9;
    
    int main() {
        vector<vector<int>> d = {{0, 3, INF, 7}, {8, 0, 2, INF}, {5, INF, 0, 1}, {2, INF, INF, 0}};
        int V = d.size();
        for (int k = 0; k < V; k++)
            for (int i = 0; i < V; i++)
                for (int j = 0; j < V; j++)
                    if (d[i][k] < INF && d[k][j] < INF && d[i][k] + d[k][j] < d[i][j])
                        d[i][j] = d[i][k] + d[k][j];
        for (auto& row : d) { for (int x : row) cout << x << " "; cout << "\n"; }
    }

    The < INF checks in C++ stop INF + INF from overflowing.

    Reconstructing the actual path

    Keep a next[i][j] matrix: initially next[i][j] = j for every edge, and whenever you improve dist[i][j] through k, set next[i][j] = next[i][k]. Then follow next from i until you reach j.

    Floyd–Warshall vs running Dijkstra V times

    Floyd–Warshall Dijkstra × V
    Time O(V³) O(V · E log V)
    Negative edges ✅ (no negative cycles) ❌
    Code size ~5 lines Longer
    Best for Dense or small graphs (V up to ~500) Large sparse graphs

    Detecting negative cycles

    After the algorithm, if any dist[i][i] < 0, vertex i lies on a negative cycle — you could loop forever and keep getting “cheaper”, so shortest paths are undefined.

    Common mistakes

    • Putting the k loop inside instead of outermost — the results become wrong.
    • Overflow when adding two “infinite” values.
    • Forgetting dist[i][i] = 0 at the start.

    Complexity at a glance

    Case / operationTimeWhy
    TimeO(V³)Three nested loops over the vertices.
    Dijkstra from every vertex (for comparison)O(V · E log V)Faster on sparse graphs, but no negative edges.
    Extra spaceO(V²)

    Quick check

    Test yourself — pick an answer to see if you got it.

    1. In the update dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]), what is k?

    2. Which loop must be the outermost?

    3. Can Floyd–Warshall handle negative edge weights?

    4. How many cells does the distance matrix have for 100 vertices?

    Saved only in this browser — no account needed.
    Spotted a mistake or a bug in the 3D model?

    Report a mistake

    in Floyd–Warshall (All-Pairs Shortest Paths). Thank you — every report makes the lesson better for the next reader.

    We'll also include a link to the step of the 3D model you're on and your browser type, so we can reproduce it.