This session is about finding shortest paths between every pair of vertices in a graph. Unlike Dijkstra’s algorithm, which starts from one source, Floyd-Warshall works with a distance matrix and gradually improves every source-destination pair.
Objectives
Do not copy. Read for understanding and the viva- Understand all-pairs shortest path computation.
- Apply Floyd-Warshall algorithm using distance matrices.
- Implement the algorithm for different graphs.
Concept
Do not copy. Read for understanding and the vivaFloyd-Warshall updates a distance matrix by allowing each vertex to become an intermediate vertex.
D[k][i][j] = min(D[k-1][i][j], D[k-1][i][k] + D[k-1][k][j])Algorithm
Write in lab recordfor k from 1 to n:
for i from 1 to n:
for j from 1 to n:
D[i][j] = min(D[i][j], D[i][k] + D[k][j])Complexity
Do not copy. Read for understanding and the viva| Metric | Value |
|---|---|
| Time complexity | O(n^3) |
| Space complexity | O(n^2) |
Question 1
Problem Statement
Write in lab recordApply Floyd-Warshall’s algorithm for the given graph. Show the matrix and find the shortest path.
Answer
Write in lab recordHere is the step-by-step application of the Floyd-Warshall algorithm for the given graph, followed by the code implementations.
Graph Analysis
Do not copy. Read for understanding and the vivaFirst, we identify the nodes and edges with their weights from the image.
- Nodes: 1, 2, 3, 4, 5
- Edges:
- 1 -> 2: 4
- 1 -> 3: 2
- 1 -> 5: -5
- 2 -> 4: 2
- 2 -> 5: 8
- 3 -> 2: 5
- 4 -> 1: 3
- 4 -> 3: 6
- 5 -> 4: 6
Initial Matrix ()
Write in lab recordWe represent this as an adjacency matrix where represents no direct edge.
Floyd-Warshall Iterations
Write in lab recordThe formula is:
Iteration (Intermediate Node 1)
Write in lab record-
Path :
-
Path :
-
Path :
Iteration (Intermediate Node 2)
Write in lab record-
Path :
-
Path :
-
Path :
Iteration (Intermediate Node 3)
Write in lab recordNo significant changes lower the current minimums. For example, for path , the current value is . The alternate path via node 3 yields: Since , no update is made.
Iteration (Intermediate Node 4)
Write in lab record-
Path :
-
Path :
-
Path :
-
Path :
-
Path :
-
Path :
-
Path :
-
Path :
Iteration (Intermediate Node 5)
Write in lab record- Path :
Final Distance Matrix
Write in lab recordThe final matrix contains the shortest path distances calculated between all pairs of nodes:
Shortest Path Example:
Write in lab recordThe shortest path from Node 1 to Node 4 is 1.
- Path:
- Cost:
Implementation
Write in lab recordLab record: write one language only. Pick yours once and every page opens on it; the other tabs are the same solution for comparison.
# Number of vertices in the graph
V = 5
# Define infinity as a large enough value.
INF = 99999
def floydWarshall(graph):
"""
Implements the Floyd-Warshall algorithm to find all pairs shortest paths.
"""
# dist[][] will be the output matrix that will finally have the shortest
# distances between every pair of vertices
dist = list(map(lambda i: list(map(lambda j: j, i)), graph))
# Add all vertices one by one to the set of intermediate vertices.
# k is the intermediate vertex
for k in range(V):
# i is the source vertex
for i in range(V):
# j is the destination vertex
for j in range(V):
# If vertex k is on the shortest path from i to j,
# then update the value of dist[i][j]
dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j])
print("Shortest distance matrix (D5):")
for i in range(V):
for j in range(V):
if dist[i][j] == INF:
print("%7s" % ("INF"), end=" ")
else:
print("%7d" % (dist[i][j]), end=" ")
print()
# Driver program to test the above program
# Mapping: 1->0, 2->1, 3->2, 4->3, 5->4
graph = [
[0, 4, 2, INF, -5],
[INF, 0, INF, 2, 8],
[INF, 5, 0, INF, INF],
[3, INF, 6, 0, INF],
[INF, INF, INF, 6, 0],
]
floydWarshall(graph)#include <stdio.h>
#define V 5
#define INF 999999
void floydWarshall(int graph[V][V]) {
int dist[V][V];
int i, j, k;
// Initialize the solution matrix same as input graph matrix
for (i = 0; i < V; i++)
for (j = 0; j < V; j++)
dist[i][j] = graph[i][j];
/* Add all vertices one by one to the set of intermediate
vertices.
---> Before start of an iteration, we have shortest
distances between all pairs of vertices such that
the shortest distances consider only the vertices
in set {0, 1, 2, .. k-1} as intermediate vertices.
----> After the end of an iteration, vertex no. k is
added to the set of intermediate vertices and the
set becomes {0, 1, 2, .. k}
*/
for (k = 0; k < V; k++) {
// Pick all vertices as source one by one
for (i = 0; i < V; i++) {
// Pick all vertices as destination for the
// above picked source
for (j = 0; j < V; j++) {
// If vertex k is on the shortest path from
// i to j, then update the value of dist[i][j]
if (dist[i][k] + dist[k][j] < dist[i][j])
dist[i][j] = dist[i][k] + dist[k][j];
}
}
}
// Print the shortest distance matrix
printf("The following matrix shows the shortest distances between every pair of vertices\n");
for (i = 0; i < V; i++) {
for (j = 0; j < V; j++) {
if (dist[i][j] == INF)
printf("%7s", "INF");
else
printf("%7d", dist[i][j]);
}
printf("\n");
}
}
int main() {
/* Let us create the following weighted graph
1 2 3 4 5
1 0 4 2 INF -5
2 INF 0 INF 2 8
3 INF 5 0 INF INF
4 3 INF 6 0 INF
5 INF INF INF 6 0
*/
int graph[V][V] = { {0, 4, 2, INF, -5},
{INF, 0, INF, 2, 8},
{INF, 5, 0, INF, INF},
{3, INF, 6, 0, INF},
{INF, INF, INF, 6, 0} };
floydWarshall(graph);
return 0;
}const V: usize = 5;
const INF: i32 = 999999;
fn floyd_warshall(graph: &[[i32; V]; V]) {
// Create a mutable copy of the graph to store distances
let mut dist = *graph;
// k is the intermediate vertex
for k in 0..V {
// i is the source vertex
for i in 0..V {
// j is the destination vertex
for j in 0..V {
// If vertex k is on the shortest path from i to j,
// then update the value of dist[i][j]
// We check for INF to prevent overflow, though with these values it's unlikely
if dist[i][k] != INF && dist[k][j] != INF {
if dist[i][k] + dist[k][j] < dist[i][j] {
dist[i][j] = dist[i][k] + dist[k][j];
}
}
}
}
}
println!("The following matrix shows the shortest distances between every pair of vertices:");
for i in 0..V {
for j in 0..V {
if dist[i][j] == INF {
print!("{:>7} ", "INF");
} else {
print!("{:>7} ", dist[i][j]);
}
}
println!();
}
}
fn main() {
/*
Graph representation (0-indexed):
Node 1 -> index 0
Node 2 -> index 1
...
*/
let graph: [[i32; V]; V] = [
[0, 4, 2, INF, -5],
[INF, 0, INF, 2, 8],
[INF, 5, 0, INF, INF],
[3, INF, 6, 0, INF],
[INF, INF, INF, 6, 0],
];
floyd_warshall(&graph);
}Question 2
Problem Statement
Write in lab recordApply Floyd-Warshall’s algorithm to compute the shortest path for the second graph. Compute the matrix.
Answer
Write in lab recordGraph Analysis
Do not copy. Read for understanding and the vivaFirst, we identify the vertices and the weighted directed edges from the image:
- Vertices:
- Edges:
- 1 -> 2: weight 3
- 2 -> 1: weight 4
- 1 -> 5: weight 9
- 2 -> 3: weight 15
- 2 -> 4: weight 5
- 4 -> 2: weight 7
- 4 -> 3: weight 5
- 5 -> 3: weight 16
- 5 -> 4: weight 8
Initial Matrix ()
Write in lab recordWe represent this as an adjacency matrix where represents no direct edge.
Floyd-Warshall Iterations
Write in lab recordIteration (Intermediate Node 1)
Write in lab recordWe check if going through Node 1 offers a shorter path.
- Path :
Iteration (Intermediate Node 2)
Write in lab recordWe check paths through Node 2.
- Path :
- Path :
- Path :
- Path :
Iteration (Intermediate Node 3)
Write in lab recordNode 3 has no outgoing edges (Row 3 contains all values except for the diagonal position), meaning no shortest paths can be improved by passing through Node 3.
Iteration (Intermediate Node 4)
Write in lab recordWe check paths through Node 4.
- Path :
- Path :
- Path :
- Path :
- Path :
Iteration (Intermediate Node 5)
Write in lab recordWe check paths through Node 5. None of the existing paths are improved by going through Node 5 (e.g., path costs , whereas a path via node 5 would cost ).
Final Matrix and Shortest Paths
Write in lab recordThe final matrix represents the absolute shortest distance between every pair of nodes:
Shortest Paths:
Write in lab record-
Shortest path from :
- Total Distance:
- Path Traversed: (Cost computation: )
-
Shortest path from :
- Total Distance:
- Path Traversed: (Cost computation: )
Implementation
Write in lab recordLab record: write one language only. Pick yours once and every page opens on it; the other tabs are the same solution for comparison.
# Number of vertices in the graph
V = 5
# Define infinity as a large enough value.
INF = 99999
def floydWarshall(graph):
"""
Implements the Floyd-Warshall algorithm to find all pairs shortest paths.
"""
# dist[][] will be the output matrix that will finally have the shortest
# distances between every pair of vertices
dist = list(map(lambda i: list(map(lambda j: j, i)), graph))
# Add all vertices one by one to the set of intermediate vertices.
# k is the intermediate vertex
for k in range(V):
# i is the source vertex
for i in range(V):
# j is the destination vertex
for j in range(V):
# If vertex k is on the shortest path from i to j,
# then update the value of dist[i][j]
dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j])
print("Shortest distance matrix (D5):")
for i in range(V):
for j in range(V):
if dist[i][j] == INF:
print("%7s" % ("INF"), end=" ")
else:
print("%7d" % (dist[i][j]), end=" ")
print()
# Driver program to test the above program
# Mapping: V1->0, V2->1, V3->2, V4->3, V5->4
graph = [
[0, 3, INF, INF, 9],
[4, 0, 15, 5, INF],
[INF, INF, 0, INF, INF],
[INF, 7, 5, 0, INF],
[INF, INF, 16, 8, 0],
]
floydWarshall(graph)#include <stdio.h>
#define V 5
#define INF 999999
void floydWarshall(int graph[V][V]) {
int dist[V][V];
int i, j, k;
// Initialize the solution matrix same as input graph matrix
for (i = 0; i < V; i++)
for (j = 0; j < V; j++)
dist[i][j] = graph[i][j];
/* Add all vertices one by one to the set of intermediate
vertices.
---> Before start of an iteration, we have shortest
distances between all pairs of vertices such that
the shortest distances consider only the vertices
in set {0, 1, 2, .. k-1} as intermediate vertices.
----> After the end of an iteration, vertex no. k is
added to the set of intermediate vertices and the
set becomes {0, 1, 2, .. k}
*/
for (k = 0; k < V; k++) {
// Pick all vertices as source one by one
for (i = 0; i < V; i++) {
// Pick all vertices as destination for the
// above picked source
for (j = 0; j < V; j++) {
// If vertex k is on the shortest path from
// i to j, then update the value of dist[i][j]
if (dist[i][k] + dist[k][j] < dist[i][j])
dist[i][j] = dist[i][k] + dist[k][j];
}
}
}
// Print the shortest distance matrix
printf("The following matrix shows the shortest distances between every pair of vertices (D5):\n");
for (i = 0; i < V; i++) {
for (j = 0; j < V; j++) {
if (dist[i][j] == INF)
printf("%7s", "INF");
else
printf("%7d", dist[i][j]);
}
printf("\n");
}
}
int main() {
/* Let us create the following weighted graph
Mapping: V1=0, V2=1, V3=2, V4=3, V5=4
V1 V2 V3 V4 V5
V1 0 3 INF INF 9
V2 4 0 15 5 INF
V3 INF INF 0 INF INF
V4 INF 7 5 0 INF
V5 INF INF 16 8 0
*/
int graph[V][V] = { {0, 3, INF, INF, 9},
{4, 0, 15, 5, INF},
{INF, INF, 0, INF, INF},
{INF, 7, 5, 0, INF},
{INF, INF, 16, 8, 0} };
floydWarshall(graph);
return 0;
}const V: usize = 5;
const INF: i32 = 999999;
fn floyd_warshall(graph: &[[i32; V]; V]) {
// Create a mutable copy of the graph to store distances
let mut dist = *graph;
// k is the intermediate vertex
for k in 0..V {
// i is the source vertex
for i in 0..V {
// j is the destination vertex
for j in 0..V {
// If vertex k is on the shortest path from i to j,
// then update the value of dist[i][j]
// We check for INF to prevent overflow
if dist[i][k] != INF && dist[k][j] != INF {
if dist[i][k] + dist[k][j] < dist[i][j] {
dist[i][j] = dist[i][k] + dist[k][j];
}
}
}
}
}
println!(
"The following matrix shows the shortest distances between every pair of vertices (D5):"
);
for i in 0..V {
for j in 0..V {
if dist[i][j] == INF {
print!("{:>7} ", "INF");
} else {
print!("{:>7} ", dist[i][j]);
}
}
println!();
}
}
fn main() {
/*
Graph representation (0-indexed):
V1 -> index 0
V2 -> index 1
V3 -> index 2
V4 -> index 3
V5 -> index 4
*/
let graph: [[i32; V]; V] = [
[0, 3, INF, INF, 9],
[4, 0, 15, 5, INF],
[INF, INF, 0, INF, INF],
[INF, 7, 5, 0, INF],
[INF, INF, 16, 8, 0],
];
floyd_warshall(&graph);
}Question 3
Problem Statement
Write in lab recordImplement the all-pair shortest path algorithm using different graphs.
Answer
Write in lab recordThis algorithm works by iteratively improving the estimate of the shortest path between two nodes by considering every other node as a potential intermediate point.
The Algorithm Logic
Do not copy. Read for understanding and the viva- Initialize the distance matrix
distwith the direct edge weights (adjacency matrix). - Loop through every node
k(from 0 to V-1) to treat it as an intermediate node. - For every pair of nodes
(i, j), check if the pathi -> k -> jis shorter than the current known pathi -> j. - Update
dist[i][j]if a shorter path is found.
Lab record: write one language only. Pick yours once and every page opens on it; the other tabs are the same solution for comparison.
# Number of vertices in the graph
V = 5
def floydWarshall(graph):
"""
Implements the Floyd-Warshall algorithm to find all pairs shortest paths.
"""
# dist[][] will be the output matrix that will finally have the shortest
# distances between every pair of vertices.
# We create a deep copy to avoid modifying the original graph structure.
dist = [row[:] for row in graph]
# Add all vertices one by one to the set of intermediate vertices.
# k is the intermediate vertex
for k in range(V):
# i is the source vertex
for i in range(V):
# j is the destination vertex
for j in range(V):
# If vertex k is on the shortest path from i to j,
# then update the value of dist[i][j]
# We check if dist[i][k] and dist[k][j] are not infinity
if dist[i][k] != float("inf") and dist[k][j] != float("inf"):
if dist[i][k] + dist[k][j] < dist[i][j]:
dist[i][j] = dist[i][k] + dist[k][j]
print("Shortest distance matrix (D5):")
for i in range(V):
for j in range(V):
if dist[i][j] == float("inf"):
print("%7s" % ("INF"), end=" ")
else:
print("%7d" % (dist[i][j]), end=" ")
print()
# Driver program to test the above program
# Mapping: V1->0, V2->1, V3->2, V4->3, V5->4
graph = [
[0, 3, float("inf"), float("inf"), 9],
[4, 0, 15, 5, float("inf")],
[float("inf"), float("inf"), 0, float("inf"), float("inf")],
[float("inf"), 7, 5, 0, float("inf")],
[float("inf"), float("inf"), 16, 8, 0],
]
floydWarshall(graph)#include <stdio.h>
// Define the number of vertices
#define V 5
// Define Infinity (a value larger than any possible path sum)
#define INF 99999
void floydWarshall(int graph[V][V]) {
// dist[i][j] will store the shortest distance from i to j
int dist[V][V];
int i, j, k;
// 1. Initialize the solution matrix same as input graph matrix
// Or we can say the initial values of shortest distances are based
// on shortest paths considering no intermediate vertices.
for (i = 0; i < V; i++) {
for (j = 0; j < V; j++) {
dist[i][j] = graph[i][j];
}
}
// 2. Add all vertices one by one to the set of intermediate vertices.
// k is the intermediate vertex.
for (k = 0; k < V; k++) {
// i is the source vertex
for (i = 0; i < V; i++) {
// j is the destination vertex
for (j = 0; j < V; j++) {
// If vertex k is on the shortest path from i to j,
// then update the value of dist[i][j]
// Check for INF to prevent integer overflow
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];
}
}
}
}
// Print the shortest distance matrix
printf("The following matrix shows the shortest distances between every pair of vertices:\n");
for (i = 0; i < V; i++) {
for (j = 0; j < V; j++) {
if (dist[i][j] == INF)
printf("%7s", "INF");
else
printf("%7d", dist[i][j]);
}
printf("\n");
}
}
int main() {
/*
Example Graph (Based on the second image provided previously):
Mapping: V1=0, V2=1, V3=2, V4=3, V5=4
Edges:
1->2 (3), 1->5 (9)
2->1 (4), 2->3 (15), 2->4 (5)
4->2 (7), 4->3 (5)
5->3 (16), 5->4 (8)
*/
int graph[V][V] = {
{0, 3, INF, INF, 9},
{4, 0, 15, 5, INF},
{INF, INF, 0, INF, INF},
{INF, 7, 5, 0, INF},
{INF, INF, 16, 8, 0}
};
floydWarshall(graph);
return 0;
}const V: usize = 5;
const INF: i32 = 999999;
fn floyd_warshall(graph: &[[i32; V]; V]) {
// Create a mutable copy of the graph to store distances.
// In Rust, arguments are immutable by default, so we clone it.
let mut dist = *graph;
// k is the intermediate vertex
for k in 0..V {
// i is the source vertex
for i in 0..V {
// j is the destination vertex
for j in 0..V {
// If vertex k is on the shortest path from i to j,
// then update the value of dist[i][j]
// Check for INF to prevent integer overflow during addition
if dist[i][k] != INF && dist[k][j] != INF {
if dist[i][k] + dist[k][j] < dist[i][j] {
dist[i][j] = dist[i][k] + dist[k][j];
}
}
}
}
}
println!("The following matrix shows the shortest distances between every pair of vertices:");
for i in 0..V {
for j in 0..V {
if dist[i][j] == INF {
print!("{:>7} ", "INF");
} else {
print!("{:>7} ", dist[i][j]);
}
}
println!();
}
}
fn main() {
/*
Graph representation (0-indexed):
V1 -> index 0
V2 -> index 1
V3 -> index 2
V4 -> index 3
V5 -> index 4
*/
let graph: [[i32; V]; V] = [
[0, 3, INF, INF, 9],
[4, 0, 15, 5, INF],
[INF, INF, 0, INF, INF],
[INF, 7, 5, 0, INF],
[INF, INF, 16, 8, 0],
];
floyd_warshall(&graph);
}