The Floyd-Warshall algorithm is a classic algorithm used to find the shortest paths between all pairs of vertices in a weighted graph. It is particularly useful for dense graphs where the number of edges is close to the square of the number of vertices. This algorithm is an example of dynamic programming and has a time complexity of \(O(V^3)\), where \(V\) is the number of vertices in the graph.

Key Concepts

  1. Graph Representation:

    • The graph is represented using an adjacency matrix.
    • If there is an edge from vertex \(i\) to vertex \(j\) with weight \(w\), then the matrix entry \(A[i][j] = w\).
    • If there is no edge between \(i\) and \(j\), \(A[i][j] = \infty\) (or a very large number).
  2. Dynamic Programming:

    • The algorithm iteratively improves the solution by considering all possible paths through intermediate vertices.
    • It uses a 3-dimensional table \(dist[k][i][j]\) where \(dist[k][i][j]\) represents the shortest path from \(i\) to \(j\) using only the first \(k\) vertices as intermediates.

Algorithm Steps

  1. Initialization:

    • Initialize the distance matrix with the given weights of the edges.
    • Set the diagonal elements to zero, i.e., \(dist[i][i] = 0\).
  2. Iterative Update:

    • For each vertex \(k\) (considered as an intermediate vertex):
      • For each pair of vertices \(i\) and \(j\):
        • Update the distance \(dist[i][j]\) to the minimum of \(dist[i][j]\) and \(dist[i][k] + dist[k][j]\).

Example

Consider the following graph:

    1       2
A ------> B -----> C
|         ^       /
|        /       /
|       /       /
|      /       /
|     /       /
|    /       /
|   /       /
|  /       /
| /       /
|/       /
D <-----/
    3

The adjacency matrix representation is:

A B C D
A 0 1 3
B 0 2
C 0
D 4 0

Initialization

dist = [
    [0, 1, ∞, 3],
    [∞, 0, 2, ∞],
    [∞, ∞, 0, ∞],
    [∞, ∞, 4, 0]
]

Iterative Update

  1. Using vertex A as an intermediate:

    • No updates needed as there are no shorter paths through A.
  2. Using vertex B as an intermediate:

    • Update \(dist[A][C]\) to \(dist[A][B] + dist[B][C] = 1 + 2 = 3\).
dist = [
    [0, 1, 3, 3],
    [∞, 0, 2, ∞],
    [∞, ∞, 0, ∞],
    [∞, ∞, 4, 0]
]
  1. Using vertex C as an intermediate:

    • No updates needed as there are no shorter paths through C.
  2. Using vertex D as an intermediate:

    • Update \(dist[A][C]\) to \(dist[A][D] + dist[D][C] = 3 + 4 = 7\) (but 3 is already smaller).
dist = [
    [0, 1, 3, 3],
    [∞, 0, 2, ∞],
    [∞, ∞, 0, ∞],
    [∞, ∞, 4, 0]
]

Code Implementation

def floyd_warshall(graph):
    # Number of vertices in the graph
    V = len(graph)
    
    # Initialize the distance matrix with the graph's adjacency matrix
    dist = [[graph[i][j] for j in range(V)] for i in range(V)]
    
    # Apply Floyd-Warshall algorithm
    for k in range(V):
        for i in range(V):
            for j in range(V):
                if dist[i][j] > dist[i][k] + dist[k][j]:
                    dist[i][j] = dist[i][k] + dist[k][j]
    
    return dist

# Example graph represented as an adjacency matrix
graph = [
    [0, 1, float('inf'), 3],
    [float('inf'), 0, 2, float('inf')],
    [float('inf'), float('inf'), 0, float('inf')],
    [float('inf'), float('inf'), 4, 0]
]

# Compute shortest paths
shortest_paths = floyd_warshall(graph)

# Print the result
for row in shortest_paths:
    print(row)

Explanation

  1. Initialization:

    • The dist matrix is initialized with the values from the input graph.
  2. Triple Nested Loop:

    • The outer loop iterates over each vertex \(k\) as an intermediate vertex.
    • The middle and inner loops iterate over each pair of vertices \(i\) and \(j\).
    • The distance \(dist[i][j]\) is updated if a shorter path is found through vertex \(k\).

Output

[0, 1, 3, 3]
[inf, 0, 2, inf]
[inf, inf, 0, inf]
[inf, inf, 4, 0]

Exercises

Exercise 1

Given the following graph, apply the Floyd-Warshall algorithm to find the shortest paths between all pairs of vertices:

    5       3
A ------> B -----> C
|         ^       /
|        /       /
|       /       /
|      /       /
|     /       /
|    /       /
|   /       /
|  /       /
| /       /
|/       /
D <-----/
    2

Adjacency matrix:

A B C D
A 0 5 2
B 0 3
C 0
D 1 0

Solution

  1. Initialization:
dist = [
    [0, 5, ∞, 2],
    [∞, 0, 3, ∞],
    [∞, ∞, 0, ∞],
    [∞, ∞, 1, 0]
]
  1. Iterative Update:
  • Using vertex A as an intermediate:

    • No updates needed.
  • Using vertex B as an intermediate:

    • Update \(dist[A][C]\) to \(dist[A][B] + dist[B][C] = 5 + 3 = 8\).
dist = [
    [0, 5, 8, 2],
    [∞, 0, 3, ∞],
    [∞, ∞, 0, ∞],
    [∞, ∞, 1, 0]
]
  • Using vertex C as an intermediate:

    • No updates needed.
  • Using vertex D as an intermediate:

    • Update \(dist[A][C]\) to \(dist[A][D] + dist[D][C] = 2 + 1 = 3\).
dist = [
    [0, 5, 3, 2],
    [∞, 0, 3, ∞],
    [∞, ∞, 0, ∞],
    [∞, ∞, 1, 0]
]

Conclusion

The Floyd-Warshall algorithm is a powerful tool for finding the shortest paths between all pairs of vertices in a graph. By understanding its dynamic programming approach and practicing with examples, you can effectively apply this algorithm to solve complex graph problems.

© Copyright 2024. All rights reserved