Day 47: Bellman-Ford Algorithm
Table of Contents
Day 47: Bellman-Ford Algorithm #
Welcome to Day 47 of our 60 Days of Coding Algorithm Challenge! Today, we’ll explore the Bellman-Ford algorithm, a versatile algorithm for finding the shortest paths from a single source vertex to all other vertices in a weighted graph.
What is the Bellman-Ford Algorithm? #
The Bellman-Ford algorithm is used to find the shortest paths from a source vertex to all other vertices in a weighted graph. Unlike Dijkstra’s algorithm, Bellman-Ford can handle graphs with negative edge weights and can detect negative cycles in the graph.
How Does It Work? #
The algorithm works by repeatedly relaxing all edges V-1 times, where V is the number of vertices in the graph. After this process, it checks for negative-weight cycles.
- Initialize distances from the source to all vertices as infinite and distance to the source itself as 0.
- Relax all edges |V| - 1 times. For each edge (u, v) with weight w, if dist[v] > dist[u] + w, then update dist[v] = dist[u] + w.
- Check for negative-weight cycles. For each edge (u, v) with weight w, if dist[v] > dist[u] + w, then there is a negative-weight cycle.
Implementing Bellman-Ford Algorithm #
Here’s an implementation of the Bellman-Ford algorithm:
def bellman_ford(graph, source):
# Step 1: Initialize distances from source to all other vertices as INFINITE
distances = {vertex: float('infinity') for vertex in graph}
distances[source] = 0
# Step 2: Relax all edges |V| - 1 times
for _ in range(len(graph) - 1):
for u in graph:
for v, w in graph[u].items():
if distances[u] != float('infinity') and distances[u] + w < distances[v]:
distances[v] = distances[u] + w
# Step 3: Check for negative-weight cycles
for u in graph:
for v, w in graph[u].items():
if distances[u] != float('infinity') and distances[u] + w < distances[v]:
print("Graph contains negative weight cycle")
return None
return distances
# Example usage
graph = {
'A': {'B': -1, 'C': 4},
'B': {'C': 3, 'D': 2, 'E': 2},
'C': {},
'D': {'B': 1, 'C': 5},
'E': {'D': -3}
}
source = 'A'
distances = bellman_ford(graph, source)
if distances:
for vertex, distance in distances.items():
print(f"Distance from {source} to {vertex}: {distance}")
Time and Space Complexity #
- Time Complexity: O(VE), where V is the number of vertices and E is the number of edges.
- Space Complexity: O(V) to store the distance array.
Advantages of Bellman-Ford Algorithm #
- Can handle graphs with negative edge weights.
- Can detect negative cycles in the graph.
- Simpler than Dijkstra’s algorithm and doesn’t require a priority queue.
Disadvantages #
- Slower than Dijkstra’s algorithm for graphs with non-negative edge weights.
- Not suitable for graphs with a large number of edges and vertices due to its time complexity.
Applications of Bellman-Ford Algorithm #
- Routing protocols in computer networks (e.g., RIP - Routing Information Protocol).
- Finding arbitrage opportunities in currency exchange.
- As a subroutine in other graph algorithms.
Exercise #
- Modify the Bellman-Ford algorithm to print the actual shortest path from the source to each vertex, not just the distances.
- Implement a function that uses the Bellman-Ford algorithm to detect if there’s a negative cycle in the graph, and if so, print the cycle.
- Use the Bellman-Ford algorithm to solve the “Currency Arbitrage” problem: Given a table of exchange rates between currencies, find a sequence of exchanges that results in a profit.
Summary #
Today, we explored the Bellman-Ford algorithm, a versatile method for finding shortest paths in a weighted graph, even when the graph contains negative edge weights. We implemented the algorithm, discussed its time and space complexity, and looked at its advantages, disadvantages, and applications.
The Bellman-Ford algorithm is particularly useful when dealing with graphs that may contain negative edge weights or when we need to detect negative cycles in a graph.
Tomorrow, we’ll dive into the world of backtracking algorithms, starting with an introduction to the concept and some classic problems. Stay tuned!