Courses › Coding Interviews › Patterns
Graphs: Topo Sort & Dijkstra
Dependency ordering, cycle detection and weighted shortest paths.
Beyond basic BFS and DFS, two graph algorithms come up again and again: topological sort for ordering dependencies, and Dijkstra for shortest paths with weights.
Representing a graph
Most problems give you an edge list. Convert it to an adjacency list:
from collections import defaultdict
graph = defaultdict(list)
for u, v in edges:
graph[u].append(v) # directed; add graph[v].append(u) for undirectedTopological sort
Orders the nodes of a directed acyclic graph so every edge goes from earlier to later. Use it for course prerequisites, build systems, task scheduling — anything with "X must happen before Y".
Signals: dependencies, prerequisites, "valid order", "can all tasks be completed?"
from collections import deque, defaultdict
def topo_sort(n, edges):
graph = defaultdict(list)
indegree = [0] * n
for before, after in edges:
graph[before].append(after)
indegree[after] += 1
queue = deque(i for i in range(n) if indegree[i] == 0)
order = []
while queue:
node = queue.popleft()
order.append(node)
for nxt in graph[node]:
indegree[nxt] -= 1
if indegree[nxt] == 0:
queue.append(nxt)
return order if len(order) == n else [] # shorter = there's a cycleO(V + E). The "fewer than n nodes processed" check doubles as cycle detection.
Dijkstra's algorithm
Shortest paths from one source when edge weights are non-negative.
import heapq
from collections import defaultdict
def dijkstra(n, edges, source):
graph = defaultdict(list)
for u, v, w in edges:
graph[u].append((v, w))
dist = [float("inf")] * n
dist[source] = 0
heap = [(0, source)]
while heap:
d, node = heapq.heappop(heap)
if d > dist[node]:
continue # stale entry
for nxt, w in graph[node]:
nd = d + w
if nd < dist[nxt]:
dist[nxt] = nd
heapq.heappush(heap, (nd, nxt))
return distO((V + E) log V).
Choosing a shortest-path algorithm
[!TIP] Practice Course Schedule · Network Delay Time