Quiz 2

22. Topological Sort & DAG Longest Path

822 words
4 min read
Python Week 1: the first filter for runtime behavior
Visual companion
Python
Type and operator map

Python Week 1: the first filter for runtime behavior

View
Revision summary

What this note is really saying

Short form

# 22. Topological Sort & DAG Longest Path > **What problem does this solve?** Some tasks must be done in order: you must put on socks before shoes, finish course prerequisites before taking advanced courses.

22. Topological Sort & DAG Longest Path

What problem does this solve? Some tasks must be done in order: you must put on socks before shoes, finish course prerequisites before taking advanced courses. A topological sort gives a linear ordering of vertices in a Directed Acyclic Graph (DAG) such that for every edge u→v, u comes before v.

1. Kahn's Algorithm (BFS-based)

How It Works

  1. Compute in-degree (incoming edges) for each vertex
  2. Start with vertices having in-degree 0
  3. Remove a vertex, decrease in-degree of its neighbors
  4. If a neighbor's in-degree becomes 0, add it to the queue (Diagram)

Implementation

python
# runnable
from collections import deque
def topological_sort_kahn(graph):
    """Return topological ordering using Kahn's algorithm.
    Time: O(V + E)
    Space: O(V)
    """
    # Compute in-degrees
    in_degree = {v: 0 for v in graph}
    for v in graph:
        for neighbor in graph[v]:
            in_degree[neighbor] += 1
    # Queue of vertices with in-degree 0
    queue = deque([v for v in graph if in_degree[v] == 0])
    result = []
    while queue:
        v = queue.popleft()
        result.append(v)
        for neighbor in graph[v]:
            in_degree[neighbor] -= 1
            if in_degree[neighbor] == 0:
                queue.append(neighbor)
    # Check if graph had a cycle
    if len(result) != len(graph):
        return None  # Cycle detected!
    return result
# DAG for getting dressed
dress_graph = {
    'undershorts': ['pants', 'shirt'],
    'pants': ['belt', 'shoes'],
    'belt': ['jacket'],
    'shirt': ['belt', 'jacket'],
    'tie': ['jacket'],
    'jacket': [],
    'socks': ['shoes'],
    'shoes': [],
    'watch': []
}
result = topological_sort_kahn(dress_graph)
print(f"Topological order: {result}")
# One valid order: ['socks', 'undershorts', 'pants', 'shoes', 'watch',
#                   'shirt', 'belt', 'tie', 'jacket']

2. DFS-based Topological Sort

How It Works

  1. Run DFS, recording postorder numbers
  2. Sort vertices by decreasing postorder number (reverse of finishing order)
python
# runnable
def topological_sort_dfs(graph):
    """Return topological ordering using DFS (reverse postorder)."""
    visited = set()
    result = []
    def dfs(v):
        visited.add(v)
        for neighbor in graph[v]:
            if neighbor not in visited:
                dfs(neighbor)
        result.append(v)  # Postorder: add after processing children
    for v in graph:
        if v not in visited:
            dfs(v)
    # Reverse to get topological order
    return list(reversed(result))
print(f"DFS-based: {topological_sort_dfs(dress_graph)}")

3. Cycle Detection

If Kahn's algorithm processes fewer than |V| vertices, the graph has a cycle.
python
# runnable
def has_cycle(graph):
    """Detect cycle in directed graph using DFS."""
    WHITE, GRAY, BLACK = 0, 1, 2
    color = {v: WHITE for v in graph}
    def dfs(v):
        color[v] = GRAY  # In current recursion stack
        for neighbor in graph[v]:
            if color[neighbor] == GRAY:
                return True  # Back edge → cycle!
            if color[neighbor] == WHITE:
                if dfs(neighbor):
                    return True
        color[v] = BLACK  # Fully processed
        return False
    for v in graph:
        if color[v] == WHITE:
            if dfs(v):
                return True
    return False
# Test
cyclic_graph = {
    'A': ['B'],
    'B': ['C'],
    'C': ['A']  # Back edge!
}
print(f"Cyclic: {has_cycle(cyclic_graph)}")  # True
print(f"DAG: {has_cycle(dress_graph)}")      # False

4. Longest Path in DAG

In a DAG, the longest path can be found in O(V + E) using DP on topological order.
python
# runnable
def longest_path_dag(graph, weights, start):
    """Find longest path from start in a weighted DAG.
    Uses DP: dist[v] = max(dist[v], dist[u] + weight(u,v))
    Processed in topological order.
    """
    topo_order = topological_sort_kahn(graph)
    if topo_order is None:
        return None  # Has cycle
    dist = {v: float('-inf') for v in graph}
    dist[start] = 0
    for u in topo_order:
        if dist[u] != float('-inf'):
            for v, w in graph[u]:
                if dist[u] + w > dist[v]:
                    dist[v] = dist[u] + w
    return dist
# Longest path example
dag = {
    'A': [('B', 3), ('C', 2)],
    'B': [('C', 1), ('D', 5)],
    'C': [('D', 4)],
    'D': []
}
print(f"Longest paths from A: {longest_path_dag(dag, 'A')}")
# {'A': 0, 'B': 3, 'C': 3, 'D': 8}  (A→B→D = 3+5=8)

Practice Questions

Q1. Find a topological order for: A→B, A→C, B→D, C→D. Q2. Can you topological-sort a graph with a cycle? Q3. Why does Kahn's algorithm use a queue instead of a stack? Q4. How does pre/post numbering in DFS help detect cycles? Q5. For a DAG with n vertices, what's the minimum and maximum number of edges?
Answers
A1. A before B and C, both before D. Valid orders: [A, B, C, D] or [A, C, B, D].
A2. No — topological sort is only defined for DAGs. A cycle means no linear ordering exists.
A3. Queue gives BFS-like behavior (any vertex with in-degree 0 works). Using a stack would also produce a valid topological sort, but the order would differ (DFS flavor).
A4. If during DFS we encounter a GRAY vertex (currently on the recursion stack), we've found a back edge → cycle. Finished/BLACK vertices are safe.
A5. Minimum: n - 1 (a single path). Maximum: n(n-1)/2 (complete DAG — all edges go from lower-index to higher-index vertices). Join Discord Previous21. BFS & DFS — Graph TraversalsNext23. Dijkstra's Shortest Path Algorithm
Document outline

Keep your place and jump directly to a heading.

Table of Contents
System Normal // Awaiting Context

Intelligence Hub

Navigate the knowledge graph to generate context. The Hub adapts dynamically to surface backlinks, related notes, and metadata insights.