直接回答:Kahn 算法(BFS 版):统计入度,入度 0 的入队,逐个取出并削减后继入度,新归零者续入队——输出即拓扑序,队空但输出不足 n 个点则有环。DFS 版:递归访问,回溯时把节点压栈,最后逆序输出——三色标记(未访/访问中/完成)判环。Kahn 判环直接、易做多源扩展;DFS 代码短但递归深度与判环标记是坑。

展开解析:应用地图:课程表 I/II(先修依赖建图,Kahn 一遍出顺序与可行性);编译依赖/任务调度(实际工程场景,注意 Diamond 依赖——同一节点被多条边指向,入度统计按边不按父节点数去重);外星文字典(从相邻单词首差异字符推导字母序边,边不存在但前缀反转是非法输入的坑);平行课程/最少学期数(Kahn 分层——每轮取走全部入度 0 节点为一级,层数即最少轮次,这是“多源 BFS 分层”的标准变形)。进阶变体:字典序最小拓扑序——队列换小顶堆(每次取可选节点中最小的);拓扑序唯一性判定——任意时刻可选节点恰一个;反图拓扑——“所有可达终点的安全节点”类题(从终点反推入度)。工程联系:构建系统(Make/Bazel 的 DAG 调度)、任务编排(Airflow DAG、K8s ownerReference 层级)、前端打包的模块依赖解析全是拓扑排序——工程里还多一层“环的报警文案”:Kahn 剩余的入度非零节点集合就是环上的点,直接可用于报错定位。实现细节:邻接表建图(稀疏图邻接矩阵浪费);Kahn 的入度数组与图分离便于复用;n 到 10^5 级时 DFS 递归爆栈改迭代或直接用 Kahn。

追问方向:为什么 Kahn 剩余节点必在环上(或可达环)?分层 Kahn 如何证明层数最少?

(约 490 字)