Shortest Path Algorithm
Introduction
The shortest path problem is a fundamental problem in graph theory and computer science. It
involves finding the shortest possible path between two vertices (nodes) in a weighted or unweighted
graph. Shortest path algorithms are widely used in navigation systems, computer networks, robotics,
artificial intelligence, and social networks.
Types of Shortest Path Problems
1. Single-Source Shortest Path (SSSP): Find the shortest paths from a given source node to all
other nodes in the graph.
2. Single-Pair Shortest Path: Find the shortest path between two specific nodes.
3. All-Pairs Shortest Path: Find the shortest paths between every pair of nodes in the graph.
4. K-Shortest Paths: Find the k-shortest paths between two nodes.
Popular Shortest Path Algorithms
1. Dijkstra’s Algorithm (Greedy Approach)
• Use Case: Finds the shortest path from a single source to all other nodes in a graph with non-
negative weights.
• Approach:
• Start from the source node.
• Use a priority queue (min-heap) to repeatedly pick the node with the smallest known
distance.
• Update distances to neighboring nodes.
• Repeat until all nodes are visited.
• Time Complexity: O((V+E)logV), where V is the number of vertices and E is the number of
edges.
• Example Usage: GPS navigation, network routing.
Python Implementation
python
CopyEdit
import heapq
def dijkstra(graph, start):
pq = [(0, start)] # Min-heap of (distance, node)
distances = {node: float('inf') for node in graph}
distances[start] = 0
while pq:
current_distance, node = heapq.heappop(pq)
if current_distance > distances[node]:
continue
for neighbor, weight in graph[node].items():
distance = current_distance + weight
if distance < distances[neighbor]:
distances[neighbor] = distance
heapq.heappush(pq, (distance, neighbor))
return distances
# Graph represented as an adjacency list
graph = {
'A': {'B': 1, 'C': 4},
'B': {'A': 1, 'C': 2, 'D': 5},
'C': {'A': 4, 'B': 2, 'D': 1},
'D': {'B': 5, 'C': 1}
}
print(dijkstra(graph, 'A'))
2. Bellman-Ford Algorithm (Dynamic Programming)
• Use Case: Works with graphs that have negative weights but no negative weight cycles.
• Approach:
• Initialize distances.
• Relax all edges (V-1) times, updating shortest paths.
• Detect negative weight cycles.
• Time Complexity: O(VE)
• Example Usage: Currency exchange (arbitrage), network protocols.
Python Implementation
python
CopyEdit
def bellman_ford(graph, start):
distances = {node: float('inf') for node in graph}
distances[start] = 0
for _ in range(len(graph) - 1):
for node in graph:
for neighbor, weight in graph[node].items():
if distances[node] + weight < distances[neighbor]:
distances[neighbor] = distances[node] + weight
return distances
graph = {
'A': {'B': 1, 'C': 4},
'B': {'C': 2, 'D': 5},
'C': {'D': -3},
'D': {}
}
print(bellman_ford(graph, 'A'))
3. Floyd-Warshall Algorithm (All-Pairs Shortest Path)
• Use Case: Finds the shortest path between all pairs of nodes.
• Approach:
• Use dynamic programming to iteratively update a matrix of shortest paths.
• Time Complexity: O(V3)
• Example Usage: Network latency analysis, routing tables.
Python Implementation
python
CopyEdit
def floyd_warshall(graph):
nodes = list(graph.keys())
dist = {node: {neighbor: float('inf') for neighbor in nodes} for node in nodes}
for node in nodes:
dist[node][node] = 0
for neighbor, weight in graph[node].items():
dist[node][neighbor] = weight
for k in nodes:
for i in nodes:
for j in nodes:
dist[i][j] = min(dist[i][j], dist[i][k] + dist[k][j])
return dist
graph = {
'A': {'B': 3, 'C': 8},
'B': {'A': 3, 'C': 2},
'C': {'A': 8, 'B': 2}
}
print(floyd_warshall(graph))
4. A Algorithm (Heuristic Search)*
• Use Case: Optimized shortest path search in large graphs (e.g., game AI, GPS routing).
• Approach:
• Uses Dijkstra’s Algorithm with a heuristic (e.g., Euclidean distance).
• Prioritizes paths more likely to reach the goal faster.
• Time Complexity: O((V+E)logV) (similar to Dijkstra’s but often faster in practice).