By Fatskills Exam Guides Team — the exam nerds behind 28,500+ quizzes and 2.1M practice questions across 500+ global exams.
"This algorithm appears in 1 out of every 3 FAANG graph interviews—master it, and you’ll detect negative cycles, handle edge cases, and prove you can optimize under constraints when Dijkstra fails."
Before tackling Bellman-Ford, ensure you understand: 1. Graph Representations (Adjacency List vs. Matrix) 2. Shortest Path Basics (Dijkstra’s Algorithm, Relaxation) 3. Time Complexity Analysis (Big-O notation for nested loops)
if dist[u] + weight < dist[v]: dist[v] = dist[u] + weight
if no_updates: break
|V|-1
dist[v]
(u, v, weight)
dist = [∞] V; dist[source] = 0
prev = [-1] V; prev[v] = u
dist[source] = 0
∞
Initialize prev array (for path reconstruction) with -1.
prev
-1
Relax All Edges |V|-1 Times
dist[u] + weight < dist[v]
prev[v] = u
Track if any updates occurred in the iteration.
Early Termination Check
If no updates in an iteration, break early (optimization).
Negative Cycle Detection (Optional)
If any dist[v] decreases, a negative cycle exists.
Return Results
dist
None
Problem: Given a directed graph with negative weights, find the shortest path from source to all nodes.
source
Graph:
Edges: [(0,1,4), (0,2,2), (1,2,5), (1,3,10), (2,4,3), (4,3,4), (3,4,5)] Source: 0
Solution (Python):
def bellman_ford(edges, V, source): dist = [float('inf')] V dist[source] = 0 prev = [-1] V # Relax all edges |V|-1 times for _ in range(V - 1): updated = False for u, v, weight in edges: if dist[u] + weight < dist[v]: dist[v] = dist[u] + weight prev[v] = u updated = True if not updated: # Early termination break # Check for negative cycles for u, v, weight in edges: if dist[u] + weight < dist[v]: return None, None # Negative cycle detected return dist, prev
Time Complexity: O(V E) Space Complexity: O(V)
O(V E)
O(V)
Why This Works: - Relaxation ensures the shortest path is found after |V|-1 iterations (longest possible path without cycles). - Early termination optimizes best-case scenarios.
Problem: Detect if a graph contains a negative cycle reachable from the source.
Edges: [(0,1,1), (1,2,-1), (2,0,-1)] # Negative cycle: 0→1→2→0 Source: 0
def has_negative_cycle(edges, V, source): dist = [float('inf')] V dist[source] = 0 # Relax |V|-1 times for _ in range(V - 1): for u, v, weight in edges: if dist[u] + weight < dist[v]: dist[v] = dist[u] + weight # Check for negative cycles for u, v, weight in edges: if dist[u] + weight < dist[v]: return True # Negative cycle exists return False
Why This Works: - After |V|-1 relaxations, any further decrease in dist[v] indicates a negative cycle.
Problem: Return the shortest path from source to target if no negative cycles exist.
target
Edges: [(0,1,4), (0,2,2), (1,2,1), (1,3,5), (2,3,8), (2,4,10), (3,4,2)] Source: 0, Target: 4
def shortest_path(edges, V, source, target): dist = [float('inf')] V dist[source] = 0 prev = [-1] V # Relax |V|-1 times for _ in range(V - 1): for u, v, weight in edges: if dist[u] + weight < dist[v]: dist[v] = dist[u] + weight prev[v] = u # Check for negative cycles for u, v, weight in edges: if dist[u] + weight < dist[v]: return None # Negative cycle # Reconstruct path path = [] if dist[target] == float('inf'): return path # No path exists current = target while current != -1: path.append(current) current = prev[current] path.reverse() return path
Why This Works: - The prev array tracks the path, and reversing it gives the correct order.
O(E)
if dist[target] == ∞
"Alright, let’s lock this in. Bellman-Ford is your go-to when Dijkstra fails—negative weights, negative cycles, or dynamic graphs. Here’s the playbook:
Common pitfalls? Forgetting to initialize the source, skipping the cycle check, or not handling unreachable nodes. Interviewers love asking about negative cycles—so always run that extra pass. Now go crush it!
You’ve got this! ?
Join 4M+ learners. Unlock unlimited quizzes, wrong-answer tracking, flashcards + reminders, study guides, and 1-on-1 challenges.