AI InterviewSearch…Search problems, topics, or pages…Ctrl KGet started
Skip to content

09 Topological sort and DAGs / Lesson 1 of 1

Topological sort — Kahn's algorithm and DP on a DAG

14 min · +10 XP · 2 exercises · 4 questions

Read the text14 min
Exercises0/2
Quiz4 q

Quick answer

What is Kahn's algorithm for topological sort?

Kahn's algorithm orders the vertices of a directed acyclic graph (DAG) so every edge points forwards. It counts each vertex's in-degree, queues every vertex with in-degree 0, and repeatedly removes one, appends it to the order and lowers its neighbours' in-degrees, queueing any that reach 0. It runs in O(V + E); fewer than V vertices placed means the graph has a cycle.

A topological order lists a DAG's vertices so every edge a → b has a before b — prerequisites before courses, tasks before what depends on them. It exists exactly when there is no cycle.

Kahn's algorithm

  • Count indeg[v], the number of edges into v.
  • Every vertex with indeg == 0 is ready: nothing has to come before it.
  • Take a ready vertex, append it, and cross off its out-edges; a neighbour that drops to 0 becomes ready.
  • Ready set a queue → any valid order. A min-heap → the lexicographically smallest one.
priority_queue<int, vector<int>, greater<>> ready;
for (int v = 1; v <= n; ++v) if (indeg[v] == 0) ready.push(v);
vector<int> order;
while (!ready.empty()) {
    int u = ready.top(); ready.pop();
    order.push_back(u);
    for (int v : adj[u]) if (--indeg[v] == 0) ready.push(v);
}
bool cycle = (int)order.size() < n;
Kahn's algorithm peels the courses with nothing left to wait for
edges = 3→1, 3→4, 2→4, 4→6, 1→6, 6→5, 1→5

Count the arrows into each course: 1 has 1, 2 has 0, 3 has 0, 4 has 2, 5 has 2, 6 has 2. Courses 2 and 3 need nothing first, so they start in the ready min-heap.

0:01 / 0:26Step 1 of 8
Transcript · 8 steps

Cycles

  • On a cycle every vertex waits for another of the cycle, so none reaches 0.
  • order.size() < n is the cycle test — no separate DFS needed.

DP on a DAG

The order is a schedule for dynamic programming: when u comes up, every path into it is already counted.

  • Longest path: best[v] = max(best[v], best[u] + w) over edges in order — O(V + E), though NP-hard on general graphs.
  • Number of paths 1 → n: ways[v] += ways[u], mod 10^9 + 7.
  • Fewest semesters (any number of courses at once): level[v] = max(level[v], level[u] + 1).

Pitfalls

  • A queue where the statement wants the smallest order — use the min-heap.
  • Recursing in a DFS topo sort on a 10^5-vertex chain: stack overflow. Kahn's is iterative.
  • Longest path with int: 10^5 edges of 10^9 needs long long.

More practice

Common questions

How do you get the lexicographically smallest topological order?

Run Kahn's algorithm with a min-heap — priority_queue<int, vector<int>, greater<>> — instead of a queue, so the smallest ready vertex is always taken next. It costs O((V + E) log V).

How does Kahn's algorithm detect a cycle?

Vertices on a cycle each wait for another vertex of the cycle, so none of them ever reaches in-degree 0. If the order ends with fewer than V vertices, the leftovers lie on a cycle or behind one, and no topological order exists.

How do you find the longest path in a DAG?

Process the vertices in topological order and relax each edge u → v with best[v] = max(best[v], best[u] + w). Every path into u is final before u is processed, so one pass gives the answer in O(V + E), even though longest path is NP-hard on general graphs.

What is the difference between Kahn's algorithm and DFS topological sort?

Both run in O(V + E). Kahn's peels in-degree-0 vertices with a queue and detects a cycle by count; the DFS version outputs vertices in reverse post-order and detects a cycle by meeting a vertex still on the recursion stack. Kahn's has no recursion depth to worry about.

Mark as readSign in to keep your place.

Topological Sort in C++: Kahn's Algorithm and Longest Path DAG

Kahn's algorithm in C++ for contests: in-degrees, a queue or min-heap for the smallest order, cycle detection by count, and DP over a DAG for longest paths.

What is Kahn's algorithm for topological sort?

Kahn's algorithm orders the vertices of a directed acyclic graph (DAG) so every edge points forwards. It counts each vertex's in-degree, queues every vertex with in-degree 0, and repeatedly removes one, appends it to the order and lowers its neighbours' in-degrees, queueing any that reach 0. It runs in O(V + E); fewer than V vertices placed means the graph has a cycle.

Lesson

A topological order lists a DAG's vertices so every edge a → b has a before b — prerequisites before courses, tasks before what depends on them. It exists exactly when there is no cycle.

Kahn's algorithm

  • Count indeg[v], the number of edges into v.
  • Every vertex with indeg == 0 is ready: nothing has to come before it.
  • Take a ready vertex, append it, and cross off its out-edges; a neighbour that drops to 0 becomes ready.
  • Ready set a queue → any valid order. A min-heap → the lexicographically smallest one.
priority_queue<int, vector<int>, greater<>> ready;
for (int v = 1; v <= n; ++v) if (indeg[v] == 0) ready.push(v);
vector<int> order;
while (!ready.empty()) {
    int u = ready.top(); ready.pop();
    order.push_back(u);
    for (int v : adj[u]) if (--indeg[v] == 0) ready.push(v);
}
bool cycle = (int)order.size() < n;
1in=02in=03in=04in=05in=06in=0readyemptyorder231465
Kahn's algorithm peels the courses with nothing left to wait for. Example: edges = 3→1, 3→4, 2→4, 4→6, 1→6, 6→5, 1→5
  1. Count the arrows into each course: 1 has 1, 2 has 0, 3 has 0, 4 has 2, 5 has 2, 6 has 2. Courses 2 and 3 need nothing first, so they start in the ready min-heap.
  2. Pop 2, the smallest ready course, and append it to the order. The heap hands out the smallest ready course, which makes the order the lexicographically smallest one. Cross off its arrows: 4 drops to 1.
  3. Pop 3, the smallest ready course, and append it to the order. Cross off its arrows: 1 drops to 0, 4 drops to 0. 1 and 4 reach 0 and join the heap.
  4. Pop 1, the smallest ready course, and append it to the order. Cross off its arrows: 6 drops to 1, 5 drops to 1.
  5. Pop 4, the smallest ready course, and append it to the order. Cross off its arrows: 6 drops to 0. 6 reaches 0 and joins the heap.
  6. Pop 6, the smallest ready course, and append it to the order. Cross off its arrows: 5 drops to 0. 5 reaches 0 and joins the heap.
  7. Pop 5, the smallest ready course, and append it to the order. It has no arrows out.
  8. The heap is empty and all 6 courses are placed: 2, 3, 1, 4, 6, 5. Every arrow points forwards in it. Had fewer than 6 been placed, the rest would sit on a cycle.

Cycles

  • On a cycle every vertex waits for another of the cycle, so none reaches 0.
  • order.size() < n is the cycle test — no separate DFS needed.

DP on a DAG

The order is a schedule for dynamic programming: when u comes up, every path into it is already counted.

  • Longest path: best[v] = max(best[v], best[u] + w) over edges in order — O(V + E), though NP-hard on general graphs.
  • Number of paths 1 → n: ways[v] += ways[u], mod 10^9 + 7.
  • Fewest semesters (any number of courses at once): level[v] = max(level[v], level[u] + 1).

Pitfalls

  • A queue where the statement wants the smallest order — use the min-heap.
  • Recursing in a DFS topo sort on a 10^5-vertex chain: stack overflow. Kahn's is iterative.
  • Longest path with int: 10^5 edges of 10^9 needs long long.

More practice

Common questions

How do you get the lexicographically smallest topological order?

Run Kahn's algorithm with a min-heap — priority_queue<int, vector<int>, greater<>> — instead of a queue, so the smallest ready vertex is always taken next. It costs O((V + E) log V).

How does Kahn's algorithm detect a cycle?

Vertices on a cycle each wait for another vertex of the cycle, so none of them ever reaches in-degree 0. If the order ends with fewer than V vertices, the leftovers lie on a cycle or behind one, and no topological order exists.

How do you find the longest path in a DAG?

Process the vertices in topological order and relax each edge u → v with best[v] = max(best[v], best[u] + w). Every path into u is final before u is processed, so one pass gives the answer in O(V + E), even though longest path is NP-hard on general graphs.

What is the difference between Kahn's algorithm and DFS topological sort?

Both run in O(V + E). Kahn's peels in-degree-0 vertices with a queue and detects a cycle by count; the DFS version outputs vertices in reverse post-order and detects a cycle by meeting a vertex still on the recursion stack. Kahn's has no recursion depth to worry about.

Exercises

The smallest course order

There are n courses 1 to n and m rules a b, each meaning course a must be taken before course b. Print an order that takes every course after all of its prerequisites; among all such orders, print the lexicographically smallest (compare the first course, then the second, …). Print IMPOSSIBLE if no order exists.

Input: n m, then m lines a b (1 ≤ n ≤ 10^5, 0 ≤ m ≤ 2·10^5, a ≠ b). Output: the n courses on one line separated by spaces, or IMPOSSIBLE.

6 7
3 1
3 4
2 4
4 6
1 6
6 5
1 5

prints

2 3 1 4 6 5

The longest path in a DAG

A directed acyclic graph has vertices 1 to n and m weighted edges. Print the largest total weight of any path (a path may start and end anywhere; a single vertex is a path of weight 0).

Input: n m, then m lines u v w (1 ≤ n ≤ 10^5, 0 ≤ m ≤ 2·10^5, 1 ≤ w ≤ 10^9). The graph has no cycle. Output: one integer.

5 6
1 2 3
1 3 2
2 4 4
3 4 6
4 5 1
2 5 2

prints

9

The path 1 → 3 → 4 → 5 weighs 2 + 6 + 1.

In this module: Topological sort and DAGs

← Checkpoint — Shortest paths · Checkpoint — Topological sort and DAGs →