Skip to main content

Floyd-Warshall Algorithm

Aditya948351
EditReport

The Floyd-Warshall Algorithm is used to find the shortest paths between all pairs of vertices in a weighted graph.

Unlike Dijkstra or Bellman-Ford, which are Single-Source Shortest Path algorithms (finding distances from one node to all others), Floyd-Warshall computes the distances between every node u and every node v.

Key Feature

Floyd-Warshall handles negative weights correctly. It can also be used to detect negative weight cycles (if the distance from a node to itself becomes negative).


Interactive Visualizationโ€‹

Below is an interactive visualizer for the Floyd-Warshall algorithm. You can click Start Floyd-Warshall to step through the dynamic programming transitions, updating the distance matrix as each intermediate vertex k is considered.


How It Worksโ€‹

The algorithm uses Dynamic Programming. The core idea is to gradually allow more intermediate vertices to form paths between any two nodes.

Stepsโ€‹

  1. Initialize a 2D dist matrix. If there's an edge from u to v, dist[u][v] = weight(u, v). Otherwise, dist[u][v] = โˆž. The diagonal dist[i][i] = 0.
  2. For each intermediate node k from 0 to V-1:
    • For every pair (i, j):
      • Check if the path i โ†’ k โ†’ j is shorter than the currently known path i โ†’ j.
      • Update: dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j])

Dry Run Exampleโ€‹

Consider the following graph:

Initial Distance Matrix:

ABCD
A05โˆž10
Bโˆž03โˆž
Cโˆžโˆž01
Dโˆžโˆžโˆž0

The algorithm now considers each vertex as an intermediate node and updates the matrix whenever a shorter path is found.

note

Unlike Dijkstra's Algorithm, Floyd-Warshall computes shortest paths between every pair of vertices simultaneously by gradually allowing more intermediate vertices.

Matrix Updatesโ€‹

After considering B as intermediate vertexโ€‹

Path A โ†’ B โ†’ C gives:

5 + 3 = 8

Updated matrix:

ABCD
A05810
Bโˆž03โˆž
Cโˆžโˆž01
Dโˆžโˆžโˆž0

After considering C as intermediate vertexโ€‹

Path A โ†’ C โ†’ D gives:

8 + 1 = 9

Final Shortest Path Matrixโ€‹

ABCD
A0589
Bโˆž034
Cโˆžโˆž01
Dโˆžโˆžโˆž0

The matrix now contains the shortest distances between every pair of vertices after considering all intermediate vertices.

Visualizationโ€‹

Negative Cycle Detectionโ€‹

One advantage of the Floyd-Warshall Algorithm is its ability to detect negative weight cycles.

A negative cycle is a cycle whose total edge weight is negative. If such a cycle exists, the shortest path is undefined because repeatedly traversing the cycle keeps reducing the path cost.

How Detection Worksโ€‹

After all vertices have been considered as intermediate vertices, inspect the diagonal elements of the distance matrix.

For every vertex i:

dist[i][i] < 0

indicates that a path exists from the vertex back to itself with a negative total cost.

Therefore, if any diagonal entry becomes negative, the graph contains a negative weight cycle.

Exampleโ€‹

Final distance matrix:

AB
A-21
B30

Here:

dist[A][A] = -2

Since the distance from A back to itself is negative, a negative cycle exists in the graph.

warning

If a negative weight cycle is present, the shortest path values are not reliable because the path cost can be reduced indefinitely by repeatedly traversing the cycle.

Detection Checkโ€‹

Pseudo-code:

for i = 0 to V-1:
if dist[i][i] < 0:
Negative Cycle Exists

This check takes only O(V) time after the Floyd-Warshall computation is complete.


Complexity Analysisโ€‹

MetricValue
Time ComplexityO(Vยณ)
Space ComplexityO(Vยฒ)

Where V = number of vertices. Because of the O(Vยณ) time complexity, it is best suited for small, dense graphs.


Implementationsโ€‹

Pythonโ€‹

def floyd_warshall(graph):
V = len(graph)
dist = list(map(lambda i: list(map(lambda j: j, i)), graph))

# Adding vertices individually
for k in range(V):
for i in range(V):
for j in range(V):
dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j])

return dist

# Example usage (INF represented as float('inf'))
INF = float('inf')
graph = [
[0, 5, INF, 10],
[INF, 0, 3, INF],
[INF, INF, 0, 1],
[INF, INF, INF, 0]
]
result = floyd_warshall(graph)

Javaโ€‹

public class FloydWarshall {
final static int INF = 99999, V = 4;

void floydWarshall(int graph[][]) {
int dist[][] = new int[V][V];
int i, j, k;

for (i = 0; i < V; i++)
for (j = 0; j < V; j++)
dist[i][j] = graph[i][j];

for (k = 0; k < V; k++) {
for (i = 0; i < V; i++) {
for (j = 0; j < V; j++) {
if (dist[i][k] + dist[k][j] < dist[i][j])
dist[i][j] = dist[i][k] + dist[k][j];
}
}
}
}
}

C++โ€‹

#include <iostream>
#include <vector>

using namespace std;
#define INF 99999

void floydWarshall(int V, vector<vector<int>>& graph) {
vector<vector<int>> dist = graph;

for (int k = 0; k < V; k++) {
for (int i = 0; i < V; i++) {
for (int j = 0; j < V; j++) {
if (dist[i][k] != INF && dist[k][j] != INF && dist[i][k] + dist[k][j] < dist[i][j]) {
dist[i][j] = dist[i][k] + dist[k][j];
}
}
}
}
}

JavaScriptโ€‹

function floydWarshall(graph) {
const V = graph.length;
const dist = Array.from(graph, row => [...row]);

for (let k = 0; k < V; k++) {
for (let i = 0; i < V; i++) {
for (let j = 0; j < V; j++) {
if (dist[i][k] + dist[k][j] < dist[i][j]) {
dist[i][j] = dist[i][k] + dist[k][j];
}
}
}
}
return dist;
}

Real-World Use Casesโ€‹

  • Flight Routes โ€” Finding the cheapest connections between all possible city pairs.
  • Transitive Closure โ€” Checking if there exists a path between every pair of nodes in a directed graph.
  • Network Routing โ€” Used in decentralized networks to update routing tables.
Finished reading? Mark this topic as complete.