Kahn’s Algorithm is an algorithm that finds a topological sort for a directed acyclic graph in time and space.

Algorithm 0

Lemma

Let denote the in-degree of , then

  1. Let be a vertex in .

  2. Find a topological sort of recursively.

  3. is a topological sort of .

This algorithm solves the problem in time and space.

std::vector<int> kahn(int n, int m, const std::vector<int> &u, const std::vector<int> &v) {
	std::vector<std::vector<int>> adj(n);
	std::vector deg(n, 0);
 
	for (int i = 0; i < m; i++) {
		adj[u[i]].push_back(v[i]);
		deg[v[i]]++;
	}
 
	std::vector<int> s(n), o;
	std::iota(s.begin(), s.end(), 0);
	while (!s.empty()) {
		int u = std::ranges::min(s, std::less(), [&](int u) -> int {
			return deg[u];
		});
		std::erase(s, u);
 
		o.push_back(u);
		for (int v : adj[u]) {
			deg[v]--;
		}
	}
	return o;
}

Algorithm 1

Based on Algorithm 0, maintaining yields an algorithm that solves the problem in time and space.

std::vector<int> kahn(int n, int m, const std::vector<int> &u, const std::vector<int> &v) {
	std::vector<std::vector<int>> adj(n);
	std::vector deg(n, 0);
 
	for (int i = 0; i < m; i++) {
		adj[u[i]].push_back(v[i]);
		deg[v[i]]++;
	}
 
	std::queue<int> q;
	for (int i = 0; i < n; i++) {
		if (!deg[i]) {
			q.push(i);
		}
	}
 
	std::vector<int> o;
	while (!q.empty()) {
		int u = q.front();
		q.pop();
 
		o.push_back(u);
		for (int v : adj[u]) {
			if (!--deg[v]) {
				q.push(v);
			}
		}
	}
	return o;
}