news 2026/9/29 20:05:19

为什么项目延期,大家总盯着“关键路径“?——拓扑排序与 AOE 网,一次讲透

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
为什么项目延期,大家总盯着“关键路径“?——拓扑排序与 AOE 网,一次讲透

带过项目的同学都有过这种瞬间:老板问"能不能提前一周上线",你脑子里刷地过一遍所有任务,然后发现——有的活拖两天没事,有的活拖一天,整个项目就得往后挪一天。

管住后者的,就是关键路径(Critical Path)。

这名字听起来像 PMP 的黑话,但它背后是一套能在 408 考卷上直接拿分的图论算法。今天把它从"项目管理"这层外衣里扒出来,看看到底在算什么。


一、先解决一个更基础的问题:任务能不能排成一条线

一个项目里,任务是有先后依赖的:写需求说明书,才能写代码;写完代码,才能测试。如果 A 必须在 B 之前,画一条从 A 指向 B 的边,整张图就是一张有向无环图(DAG)。

有环就有问题——A 等 B、B 等 C、C 又等 A,谁也别想开工。所以第一步,得判断"这些任务能不能排出一个合理的先后顺序",这就是拓扑排序。

它的思路朴素到有点好笑:每次挑一个"没人依赖它"的活儿先干。用图论的话说,就是反复找入度为 0的顶点,删掉它和它发出的边。一直删下去:

  • 删光了 → 得到一条合法顺序;
  • 删不干净(还有顶点剩着)→ 图里有环,依赖关系自相矛盾。

Kahn 算法写出来就几行:

fromcollectionsimportdequedeftopological_sort(n,edges):# edges: [(u, v)],表示 u 必须先于 vindeg=[0]*n g=[[]for_inrange(n)]foru,vinedges:g[u].append(v)indeg[v]+=1q=deque([iforiinrange(n)ifindeg[i]==0])order=[]whileq:u=q.popleft()order.append(u)forving[u]:indeg[v]-=1ifindeg[v]==0:q.append(v)returnorderiflen(order)==nelseNone# None 说明有环

拓扑排序是 408 数据结构"图"一章的常客,常以选择题出现(比如"下面哪个序列是合法的拓扑序"),偶尔在大题里露脸。邻接表实现的时间复杂度是O ( V + E ) O(V+E)O(V+E),这个结论要能张口就来。


二、光排出来还不够,得知道哪些活儿"拖不得"

拓扑排序只回答"能不能排、怎么排"。但老板问的是"提前上线行不行",这要算的是时间。

这时候把图升级成AOE 网:顶点表示"事件"(某个里程碑完成了),边表示"活动"(一件事),边上带权值,表示这件事要花多少天。一个事件,必须等它所有入边代表的活动都干完,才算发生。

对每个事件,我们关心两个数:

  • 最早发生时间 ve:这件事最早什么时候能成。它等于"所有通往它的事件里,最晚的一个最早时间 + 边权"。从源点一路往前推:

v e ( v j ) = max ⁡ ( v i , v j ) ∈ E { v e ( v i ) + w ( v i , v j ) } ve(v_j) = \max_{(v_i, v_j) \in E}\{ve(v_i) + w(v_i, v_j)\}ve(vj​)=(vi​,vj​)∈Emax​{ve(vi​)+w(vi​,vj​)}

  • 最迟发生时间 vl:这件事最晚得在什么时候成,才不会拖累整体工期。从汇点往回倒推:

v l ( v i ) = min ⁡ ( v i , v j ) ∈ E { v l ( v j ) − w ( v i , v j ) } vl(v_i) = \min_{(v_i, v_j) \in E}\{vl(v_j) - w(v_i, v_j)\}vl(vi​)=(vi​,vj​)∈Emin​{vl(vj​)−w(vi​,vj​)}

有了事件的两个时间,边(活动)的松紧就出来了:

  • 活动最早开始:e = v e ( v i ) e = ve(v_i)e=ve(vi​)
  • 活动最迟开始:l = v l ( v j ) − w l = vl(v_j) - wl=vl(vj​)−w
  • 时间余量:l − e l - el−e

时间余量为 0 的活动,就是关键活动。它们首尾相接,连成的那条从源点到汇点的最长路径,就是关键路径。

为什么是"最长"而不是"最短"?因为项目总工期等于从开始到结束最长的那条路——最短的路再快也没用,最后得等最慢的那条。所以关键路径 = DAG 里的最长路径,这跟 Dijkstra 求最短路径刚好是镜像。


三、用泡茶把整个流程过一遍

烧水 5 分钟、洗茶壶 1 分钟、洗茶杯 2 分钟、泡茶 1 分钟。依赖关系:烧水不依赖别的,洗壶洗杯不依赖烧水,但泡茶必须等烧水和洗壶都完成。

算下来你会发现,决定你多久能喝上茶的,是"烧水 → 泡茶"这条 6 分钟的路。洗茶杯那 2 分钟哪怕你多花一倍,只要别超过 6 分钟的总工期,就没人能察觉。余量,就是你可以摸鱼的空间;关键路径,就是你摸不得的地方。

这个道理放到软件工程里一模一样:真正决定发布日期的,永远不是那些"看起来忙"的活,而是那几件一环扣一环、半点拖不得的事。


四、顺带说一句

很多人学图论,是把拓扑排序、最短路径、最小生成树当成几个孤立算法去背的。其实它们回答的是同一个问题的不同侧面:在一堆有约束的事情里,怎么安排、怎么取舍。谁先谁后(拓扑)、怎么最快(最短路径)、怎么最省(最小生成树)、哪里拖不得(关键路径)。

把这四件事摆在一起看,图这一章反而简单了——你不是在背四个算法,你是在学"怎么给有依赖的事做计划"。


数据结构是 408 的重头戏,想系统跟学的,推荐 B站【408实验室】的《数据结构》。

图相关的兄弟篇我也都写过:为什么导航能算出"最短路线"(Dijkstra 算法)、为什么修路要"连成网、又花最少的钱"(最小生成树)、一个数组就敢说判断亲戚关系快得离谱(并查集),配合着看,图这一章能串成一条线。

备考时被"关键路径求 ve/vl 老是算错"卡住的,可以把这类题丢进 CoLearn(yantucs.com)的AI 答疑让 AI 一步步带你把 ve、vl 各推导一遍,再用AI 错题集把反复错的那几道收起来专项突破。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/29 20:04:49

2026年,洪梅镇这座水乡小镇,正在悄悄发生哪些新变化?

最近和几位在东莞洪梅镇办厂的老朋友喝茶,大家不约而同地聊到一个话题:洪梅镇这两年的变化,确实有点“快得让人反应不过来”。作为东莞水乡功能区的核心镇之一,洪梅过去给人的印象是“偏、小、慢”。但2026年刚开年,我…

作者头像 李华
网站建设 2026/9/29 20:03:54

开源Chrome取证工具hindsight:一键提取浏览器痕迹

入行做取证分析那几年,我几乎每次遇到“这台电脑到底看了什么、下过什么、跟谁联系过”这类问题时,第一反应都是同一个行动:先把浏览器的痕迹盘出来。而在所有浏览器里,Chrome 的痕迹最集中、最结构化,也最适合用一套可…

作者头像 李华
网站建设 2026/9/29 20:03:45

内蒙古清障车生产厂家筛选名录,口碑公司汇总

清障车行业基础认知什么是清障车,核心属性与应用范围是什么?清障车也叫道路救援车、拖车,是专门用于道路故障车辆、事故车辆拖拽转运的专用工程机械设备,核心作用是快速清理路面障碍,协助道路恢复正常通行,是道路应急…

作者头像 李华
网站建设 2026/9/29 20:03:25

dsh-smooth-stream 到手后的完整装法,含本地预览验证

DSH Web UI 里,大模型的长篇输出本来是按网络分块「砸」到屏幕上的:一个数据包可能几毫秒送来数百字符,下一个分块却要等数十毫秒。dsh-smooth-stream 把这套离散的到达事件换成了两个每帧连续积分的物理状态机——揭示节奏引擎逐帧喂字&…

作者头像 李华
网站建设 2026/9/29 20:03:25

能源行业转大模型:先别急着把历史工单喂给模型

版权与内容来源声明 本文为原创整理。文中涉及官方文档、开源仓库、论文与公开报道的内容,均在附表 A 中标注来源;引用官方原文保持原样,不作改写。文中命令、版本号与界面截图以本文成文时的实测/核验结果为准,标注「待验证」的部…

作者头像 李华
网站建设 2026/9/29 20:03:22

通信网理论基础期末复习题及答案:三轮刷题法+五大避坑要点

简介:面向通信工程、计算机网络等专业学生,这份复习资料围绕通信网理论基础期末高频考点整理,包含PSTN与IP网络对比、TDD/FDD优缺点、OFDM/FDMA/TDMA/CDMA/WDMA技术辨析、一次群与二次群速率计算、分组交换/虚电路/数据报、三网融合主要技术&…

作者头像 李华