“使每条弧 $(v i,v j)\in A$ 都满足 $i<j$。这样的排列存在,当且仅当 $D$ 是有向无环图(DAG)。必要性很直接:若有向圈上的每条弧都从前指向后,沿圈一周会推出某个顶点…”
形式陈述 ​
有向图
直觉
DAG 用“没有有向环”表示纯依赖关系:沿箭头只能向前,不能经过若干依赖又回到自己,因此依赖可以从前到后展开。每条路径都有限,因而至少存在入度为零的源和出度为零的汇;拓扑序把偏序补成某个兼容全序,却不抹掉哪些任务原本可并行。很多一般图上的循环依赖困难,在 DAG 上都转化为一次线性扫描。
例子与边界
边
课程先修图和构建系统依赖应形成 DAG;若 A 依赖 B、B 又依赖 A,就不存在可执行顺序。若所用有向图变体允许自环,一条自环也已经构成有向圈。树定向后是 DAG,但 DAG 可有共享后继和多个父节点。无向图“无环”得到森林,与 DAG 概念不同;有向图即使底层无向图有环,例如把三角形边统一朝同一拓扑方向,也可能仍是 DAG。若 Kahn 算法提前没有入度零点且仍有未删顶点,剩余部分必含有向圈。DAG 上的最短路即使有负边也可按拓扑序松弛。
推论与应用
拓扑排序是识别和利用 DAG 的基本算法。把每个顶点看成任务时,拓扑序只给出一个合法串行次序;工作—深度模型进一步区分总工作与最长依赖链,使互不依赖的顶点可以并行执行。两项指标不能由“有拓扑序”自动推出。
DAG 动态规划、构建系统、版本与课程依赖、任务调度、数据流和因果图都利用这一结构。若控制流图无环,数据流事实可沿拓扑序一次传播;出现回边后,同一方程组通常要由单调数据流分析迭代到不动点。DAG 在这里描述依赖形状,抽象域与转移函数给出语义,worklist 才是求解算法。
支配树研究的是单入口有向图中所有入口路径的必经关系,即使图本身有环也可定义;树宽动态规划则沿树分解处理一般图,不要求原图是 DAG。压缩强连通分量后得到的凝聚图必为 DAG,正是把有环输入接到这些 DAG 方法之前必须完成的结构化步骤。
参考资料
- Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein, Introduction to Algorithms, 4th ed., MIT Press, 2022,§20.4, topological sorting and DAGs。
- Jon Kleinberg and Éva Tardos, Algorithm Design, Pearson, 2005,§3.6, directed acyclic graphs and topological ordering。