Graph Theory: Multi-source and Single-source Shortest Path Algorithms

Shortest path problems in graph theory often rely on the concept of relaxation. Relaxation occurs when a path from node u to v can be shoretned by routing through an intermediate node k, i.e., if dist[u][v] > dist[u][k] + dist[k][v], we update dist[u][v] accordingly.

Floyd-Warshall Algorithm (All-Pairs Shortest Paths)

To compute shortest paths between all pair of vertices, the Floyd-Warshall algorithm uses dynamic programming. Define dp[k][i][j] as the shortest distance from i to j using only vertices numbered from 1 to k as intermediates. The recurrence is:

dp[k][i][j] = min(dp[k-1][i][j], dp[k-1][i][k] + dp[k-1][k][j])

Since each state depends only on the previous layer (k-1), we can optimize space by using a 2D array and iterating k in the outermost loop:

for (int k = 0; k < n; ++k)
    for (int i = 0; i < n; ++i)
        for (int j = 0; j < n; ++j)
            dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j]);

This yields the all-pairs shortest paths in O(n³) time with O(n²) space.

SPFA (Single-Source Shortest Paths)

For single-source shortest paths, especially in graphs with negative weights (but no negative cycles), the Shortest Path Faster Algorithm (SPFA)—a queue-optimized version of Bellman-Ford—is effective.

Maintain an array dist[] where dist[v] stores the shortest distance from the source s to v. Initialize dist[s] = 0 and others to infinity. Use a queue to process nodes whose outgoing edges might relax neighboring distances.

When relaxing an edge u → v with weight w, if dist[v] > dist[u] + w, update dist[v] and enqueue v—but only if it’s not already in the queue (tracked via a inQueue[] boolean array).

void spfa(int source) {
    queue<int> q;
    vector<bool> inQueue(n, false);
    vector<int> dist(n, INT_MAX);
    
    dist[source] = 0;
    q.push(source);
    inQueue[source] = true;

    while (!q.empty()) {
        int u = q.front(); q.pop();
        inQueue[u] = false;

        for (auto &edge : adj[u]) {
            int v = edge.to;
            int weight = edge.weight;
            if (dist[u] + weight < dist[v]) {
                dist[v] = dist[u] + weight;
                if (!inQueue[v]) {
                    q.push(v);
                    inQueue[v] = true;
                }
            }
        }
    }
}

Although SPFA has a worst-case time complexity of O(VE), it often performs efficiently in practice on sparse graphs or those without adversarial edge structures.

Tags: Floyd-Warshall SPFA graph-theory shortest-path dynamic-programming

Posted on Wed, 03 Jun 2026 18:20:34 +0000 by little_tris