kahn算法拓扑排序需确保入度统计准确且bfs遍历不漏节点:按实际顶点数n初始化in_degree数组,对每条边(u,v)执行in_degree[v]++;重复边需去重;编号不连续时改用unordered_map;环检测应检查bfs后in_degree是否全为0。

直接用 Kahn 算法做拓扑排序,核心就两件事:入度统计必须准,BFS 遍历必须不漏节点。图里哪怕只多一条边、少算一个入度,结果就可能为空或错序——这不是逻辑问题,是初始化错误。
入度数组怎么初始化才不会越界或漏统计
常见错误是把 in_degree 开成 vector<int>(n-1)</int> 或者遍历时只扫 adj[u] 却忘了 u 本身可能被别人指向。正确做法是:先按顶点总数 n 分配空间,再对每条边 (u, v) 做 in_degree[v]++,不管 u 是否在邻接表中出现过。
-
n必须是图中实际顶点数(比如编号从0到n-1),不能靠adj.size()推断——邻接表可能为空但顶点存在 - 如果输入边含重复边(如多次
addEdge(0, 1)),in_degree[1]会被重复加,得提前去重或用set存邻接关系 - 若顶点编号不连续(如只有节点
0、2、5),不能直接用数组,得改用unordered_map<int int></int>
queue 里 push 的条件必须严格是 in_degree[v] == 0
有人写成 if (in_degree[v] ,这会导致未初始化的节点(值为随机内存)被误推入队列;也有人在更新后没检查是否为 0 就直接 push,结果队列塞进大量无效节点。Kahn 的推进唯一依据就是「此刻入度归零」。
- 初始化阶段:只 push 所有初始
in_degree[i] == 0的i,别漏、别多 - 更新阶段:每次
--in_degree[v]后,**必须立刻判断是否等于 0**,再决定是否push(v) - 不要在循环外统一收集「下次要 push 的节点」,延迟判断会破坏 BFS 层级顺序,导致序列不合法
如何可靠判断图含环而不只是返回空 vector
很多人只检查 topo_order.size() == n,但这只能说明「没排完」,不能定位是环还是孤立节点未连通。真正要确认环,得在 BFS 结束后补一句:如果还有任何 in_degree[i] > 0,那一定成环。
- 环检测不能只依赖最终长度——比如图有两个连通分量,其中一个有环、另一个无环,
topo_order可能非空但不完整 - 更稳妥的做法是 BFS 后遍历一遍
in_degree数组,只要发现任意位置值 > 0,就说明该节点永远无法入队,即存在环 - 如果业务需要区分「无环但不连通」和「有环」,就得额外跑一次 DFS 或并查集确认连通性,Kahn 本身不提供这个信息
最易被忽略的是:Kahn 算法输出的拓扑序列不唯一,但所有合法序列都必须满足「任意边 (u, v) 中 u 在 v 前」。如果你的测试用例总得到不同顺序,别急着调代码——先确认输入图本身是否允许多种合法排列。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











