直接回答:课程与先修关系构成有向图,「能否完成全部课程」等价于「图是否无环」,用拓扑排序判定。Kahn 算法(BFS):统计每个节点入度,入度为 0 的入队;反复取出队首、输出、并把它所有邻接点入度减 1、减到 0 再入队。若最终输出的节点数等于总数则无环,否则剩下的节点都在环上。
展开解析:DFS 版本用三色标记:白(未访问)→ 灰(访问中)→ 黑(已完成),遍历中遇到灰节点即发现回边、存在环——「灰节点冲突」是 DFS 判环的核心判据。复杂度都是 O(V + E)。工程里拓扑排序的应用值得主动提:构建系统(Makefile/Bazel 的依赖调度)、任务编排、包管理器安装顺序、Vue/前端模块的依赖解析。变体:课程表 II 要求输出一个合法修课顺序(Kahn 自然产出);「按字典序最小的拓扑序」把队列换成最小堆;判断拓扑序唯一性(每步队列长度是否恒为 1)。追问方向:为什么 Kahn 剩下来的节点必有环、并行场景下按层出队如何得到最短完成轮次。
示例:
from collections import deque
def can_finish(num_courses, prerequisites):
indeg = [0] * num_courses
adj = [[] for _ in range(num_courses)]
for course, pre in prerequisites:
adj[pre].append(course)
indeg[course] += 1
queue = deque(i for i, d in enumerate(indeg) if d == 0)
done = 0
while queue:
node = queue.popleft()
done += 1
for nxt in adj[node]:
indeg[nxt] -= 1
if indeg[nxt] == 0:
queue.append(nxt)
return done == num_courses