首页指南 › 关键路径法:算法、公式与算例

关键路径法:算法、公式与算例

关键路径是项目中相互依赖的任务里最长的一条链。它的长度就是项目最短可能工期——这条链上每延误一天,完工就晚一天。

gantts.app 编辑部更新于 2026年7月19日4 分钟阅读

本页内容
  1. 基本想法
  2. 几个必须先厘清的术语
  3. 逐步计算:五个步骤
  4. 一个完整算例,连算术一起
  5. CPM、PERT 与关键链
  6. 总浮动时间、自由浮动时间与负浮动时间
  7. gantts.app 是怎么算的(以及它和教科书的差别)
  8. 在 gantts.app 里看关键路径
正推、逆推,然后读出浮动时间:
A · 3B · 5C · 2D · 4关键路径: A → B → D浮动时间 (C): 3工期: 12

基本想法

并非每项任务对工期的影响都一样。有些有余量,可以推迟而不影响完工;有些一点余量都没有——这些构成关键路径。链上的任务叫关键任务,因为它们的浮动时间为零:没有任何富余,所以关键任务延误一天,项目完工日期就一对一地后移一天。

关键路径法(Critical Path Method,CPM)由 Morgan Walker 和 James Kelley 在 1950 年代末做工厂检修排期时提出。它的价值是聚焦:几十项任务里,直接指出卡住完工日期的那几项。

几个必须先厘清的术语

把它们串起来:总浮动时间 = LS − ES = LF − EF。两种算法结果必然相同,可以互相校验;结果为零,这项活动就是关键的。

逐步计算:五个步骤

  1. 列出活动与依赖关系。每项活动、它的工期,以及它的前置任务。
  2. 画出网络。从唯一的开始节点连到唯一的结束节点。
  3. 正推求 ES / EF。从左往右:第一项活动 ES = 0,EF = ES + 工期;后续每项的 ES 取所有前置任务 EF 中的最大值——只要还有一个前置没完成,它就动不了。末端最大的那个 EF 就是项目工期。汇合处取最大值,是手算最常出错的一步。
  4. 逆推求 LS / LF。从右往左:最后一项活动的 LF 等于项目工期,LS = LF − 工期;更早每项的 LF 取所有紧后活动 LS 中的最小值——它必须赶在最早需要它的那项之前完成。正推取最大值、逆推取最小值,这一对相反的规则就是全部机关。
  5. 算浮动时间。浮动时间 = LS − ES。浮动时间为零的活动首尾相连,就是关键路径。
A · 3B · 5C · 2D · 4关键路径: A → B → D浮动时间 (C): 3工期: 12
正推定出最早时间,逆推定出最晚时间,两者之间的差就是浮动时间。差为零即关键。

一个完整算例,连算术一起

一个物流仓库的货架安装工程,九项活动,工期单位是工作日。下面每一个数字都只用到加法和减法。设第 0 天为 3 月 2 日(周一)。

青云仓储 B 库货架安装。九项活动,工作日。

活动工期(天)前置任务
A — 现场勘测4
B — 货位布置方案设计6A
C — 施工图审查与消防报建10A
D — 货架采购(长周期)15B
E — 库区清空腾挪5A
F — 地坪修补8C、E
G — 电气一次配管6F
H — 货架安装9D、G
I — 监理验收与竣工验收3H

网络里一共三条路径,各自求和:

  • A → C → F → G → H → I = 4 + 10 + 8 + 6 + 9 + 3 = 40 天
  • A → B → D → H → I = 4 + 6 + 15 + 9 + 3 = 37 天
  • A → E → F → G → H → I = 4 + 5 + 8 + 6 + 9 + 3 = 35 天

40 天最长,答案就是它。下面的正推逆推既是证明,也顺便给其余活动的余量定价。

活动工期ES = max(前置 EF)EFLF = min(紧后 LS)LS总浮动时间关键?
A — 现场勘测40(无前置)0+4 = 4min(7, 4, 9) = 44−4 = 00
B — 方案设计64(A)4+6 = 1013(D)13−6 = 73
C — 图审与报建104(A)4+10 = 1414(F)14−10 = 40
D — 货架采购1510(B)10+15 = 2528(H)28−15 = 133
E — 库区清空54(A)4+5 = 914(F)14−5 = 95
F — 地坪修补8max(14, 9) = 1414+8 = 2222(G)22−8 = 140
G — 电气配管622(F)22+6 = 2828(H)28−6 = 220
H — 货架安装9max(25, 28) = 2828+9 = 3737(I)37−9 = 280
I — 竣工验收337(H)37+3 = 4040(项目结束)40−3 = 370

有两行承载了整个方法。F 从第 14 天开始而不是第 9 天,它等的是图审报建,不是库区清空。H 从第 28 天开始而不是第 25 天:电气这条链比货架到货还晚。A 的 LS 算出来正好是 0,这是校验——大于 0,就说明 40 天不是最短工期。

浮动时间为零的 A、C、F、G、H、I 构成关键路径,恰好是最先加出来的那条 40 天的链。浮动时间也和路径长度对得上:B 和 D 在 37 天那条路径上,40 − 37 = 3;E 在 35 天那条上,40 − 35 = 5某条路径上的浮动时间,永远等于项目工期减去这条路径的长度——这是校验自己算术最快的办法。

现在让某项延误。图审报建(C)不是 10 天而是 14 天,关键活动上晚了四天。从 C 重跑正推:EF = 4 + 14 = 18,于是 F 的 ES 18 / EF 26,G 的 ES 26 / EF 32,H 的 ES max(25, 32) = 32 / EF 41,I 的 EF 变成 44

项目一天对一天地推后了——没有任何东西吸收这次延误,因为根本没有可用来吸收的东西。而其余所有人都变富了:从 LF(I) = 44 重跑逆推,B 的浮动时间变 7、D 变 7、E 变 9,各自都长了四天。别处的余量,是关键路径上的延误制造出来的。

再来一次超支浮动时间。把 C 改回 10 天,让货架采购(D,浮动时间 3)从 15 天变成 20 天——在一项非关键活动上晚了五天。D 的 EF 变成 10 + 20 = 30,于是 H 的 ES max(30, 28) = 30 / EF 39,I 在第 42 天完成。

晚两天,不是五天:前三天是从 D 自己的浮动时间里出的,只有超支的那部分传到了终点。浮动时间是一笔预算,只能花一次。而且关键路径移位了——A → B → D → H → I 现在是 4 + 6 + 20 + 9 + 3 = 42 天,原来那条图审链反而多出 2 天浮动时间。你一直在盯的那几项活动,已经不是要紧的那几项了,而如果没有东西替你重算,谁也不会告诉你这件事。

ABC自由浮动时间总浮动时间
浮动时间是一笔预算。花得比拥有的少,完工日期不动;花超了,只有超出的部分传到终点。

CPM、PERT 与关键链

CPM 每项任务只用一个确定工期,输出关键路径和浮动时间,适合估算比较可靠的场合。

PERT 给三个估计——乐观 O、最可能 M、悲观 P——按 (O + 4M + P) / 6 加权。设计任务估 2、4、12 天,期望工期就是 (2 + 16 + 12) / 6 = 5 天,比"最可能"的 4 天多一天,这一天正是长尾风险的定价。常见做法是用 PERT 估工期,再拿它跑 CPM。

关键链来自约束理论,在 CPM 之上加入资源约束,把各任务里分散的余量集中成放在链尾的缓冲。当决定进度的是共用资源时更合适。

总浮动时间、自由浮动时间与负浮动时间

上文说的"浮动时间"都是总浮动时间:一项活动在项目完工日期移动之前能推迟多久。单看它会误导人,因为总浮动时间常常是共享的。自由浮动时间问的是更严格的问题——这项活动推迟多久才会打扰到任何一个紧后活动?公式是 紧后活动中最早的 ES − 本活动 EF

总浮动时间是交付期能吸收的量,自由浮动时间是你不用打招呼就能花的量。同一条链上的两位负责人如果各自按总浮动时间做打算,他们会把同一批天数各花一遍。

负浮动时间意味着出了问题:最晚开始落在了最早开始之前,通常是因为有人指定的交付期早于逻辑允许的最早日期。−4 不是富余,它读作"这件事本该四天前就开始"。

gantts.app 是怎么算的(以及它和教科书的差别)

这一点值得说准确,因为我们的正推不是上面那一套,而差别就落在浮动时间这一列上。

教科书的 CPM 不管你把横条画在哪:它把每项活动都摆到前置任务允许的最早位置,所以 E 从第 4 天开始,无论你有没有把它摆在那儿。gantts.app 跑的是"按摆放位置"的 CPM——每项任务从它自己被摆放的开始日期起算,前置任务只能把它往后推,永远不会往前拉。写成代码就是一个 max:最早开始先取任务自身的开始,只有当约束要求更晚时,依赖关系才把它抬高。

把 E 的横条摆在第 8 天而不是第 4 天,差别就是一个数字。教科书 CPM 仍然报 ES 4、浮动时间 5 天。我们报 ES 8,而逆推不变(LS 9),浮动时间是 1 天。两个都对,只是回答的问题不同:教科书问的是逻辑允许多少余量,我们问的是这份画出来的计划还剩多少余量。

理由是它首先是一张图:一个会悄悄搬动任务的正推,等于为一份并不在屏幕上的进度计划打印浮动时间。拖动横条是一条指令,我们就当它是指令。

其余部分是常规的。最晚完成取紧后活动最晚开始中的最小值(或项目结束日),浮动时间是 LS − ES,滞后量和非完成-开始的连线都走同一遍推算。浮动时间小于或等于零时任务即为关键,所以负浮动时间会显示出来而不是被抹掉。另有三点:

想要教科书那种行为——所有任务都拉回逻辑允许的最早日期——点自动排程。它重跑一遍正推,只改一条规则:有前置任务的任务完全由约束驱动,不管它现在摆在哪;没有前置任务的任务原地不动,当锚点。点完之后,两种算法结果一致。

完成 → 开始 + 延隔时间A延隔时间 3dBB 等待 A + 3d
滞后量在不打断连线的前提下把约束往后挪。关键路径是穿过滞后量的,所以三天的等待就是交付期的三天。

在 gantts.app 里看关键路径

手算一遍是理解 CPM 的必经之路,但你不会想在每次估算变动时都重算一遍——而且上面第二次延误已经说明,路径本身是会移位的。

  1. 打开 gantts.app,用+ 任务◆ 里程碑把九项活动加进去,在天数列填工期。
  2. 前置任务列直接按行号写依赖关系,多个用逗号分隔,例如 F 那一行写 3,5;也可以从横条边缘的小圆点拖到目标横条上。
  3. 工作日历登记法定节假日和调休上班日,工期才按真实工作日展开。
  4. 自动排程,把每项任务拉回依赖关系允许的最早日期——这一步之后,结果与教科书 CPM 一致。
  5. 勾上关键路径,零浮动的那条链会画成斜纹;天数总浮动时间可在里显示出来。
  6. 改一个工期试试:把 C 从 10 改成 14,高亮和日期立刻重算,不用重跑任何一遍手算。
  7. 计划谈定后存一版基准,再用⬇ 导出出 PDF、PNG、Excel 或 PowerPoint。

它还告诉你精力花在哪里有效:给 E 加人对完工毫无帮助,因为它有 5 天浮动时间;在 C 上省一天,项目就真的早一天完工。关键路径不是计划的固有属性,而是某一时刻的快照,每周更新后都要重算——手算九项尚可,六十项就不现实。

刚接触排程的话,先读什么是甘特图,再看甘特图怎么做,或者直接从模板库拿一份现成计划。

关键路径在项目过程中会变。一项有三天浮动时间的任务若延误四天,它自己就成了关键任务。因此关键路径不是开工时算一次,而是每次更新都要重算。

常见问题

什么是关键路径?

相互依赖的任务中最长的一条链。它的长度等于项目最短工期,链上任务没有浮动时间,因此其中任何一项延误一天,完工就晚一天。

关键路径怎么计算?

先列出所有任务的工期和前置任务,再正推求最早开始与最早完成(汇合处取最大值),然后从项目工期逆推求最晚完成与最晚开始(分叉处取最小值),最后用最晚开始减最早开始得到浮动时间。浮动时间为零的任务首尾相连,就是关键路径。

什么是总浮动时间?

一项任务在不推迟项目完工的前提下可以推迟的时间,等于最晚开始减最早开始,也等于最晚完成减最早完成。注意它由整条支路共享:前面的任务用掉了,后面就没有了。

正推和逆推有什么区别?

正推从项目开始向后走,算每项任务的最早开始和最早完成,最后得到项目最短工期;逆推从这个工期往回走,算在不推迟完工的前提下每项任务最晚能什么时候开始和完成。两者之差就是浮动时间。

CPM 和 PERT 有什么区别?

CPM 每项任务用一个确定工期,关注关键路径和浮动时间;PERT 用乐观、最可能、悲观三个估计按 (O + 4M + P) / 6 加权,用来处理工期不确定性。实际项目里常常先用 PERT 估工期,再用 CPM 排关键路径。

关键路径可能有多条吗?

可能。在依赖密集的计划中,多条并行路径长度相同,于是全部成为关键路径。这时项目没有任何缓冲,任何一条路径上的延误都会直接体现在完工日期上,风险显著上升。

总浮动时间和自由浮动时间有什么区别?

总浮动时间是项目完工日期移动之前一项活动能推迟多久;自由浮动时间是它打扰到任何一个紧后活动之前能推迟多久,等于紧后活动中最早的 ES 减去本活动的 EF。总浮动时间沿整条链共享,自由浮动时间是这项活动私有的。gantts.app 只报总浮动时间,界面上没有自由浮动列。

gantts.app 算出来的浮动时间为什么和我手算的不一样?

因为它跑的是"按摆放位置"的 CPM:每项任务从你摆放的开始日期起算,依赖关系只能把它往后推,永远不会往前拉。教科书 CPM 则把每项任务都摆到逻辑允许的最早位置。想让两者一致,点"自动排程",它会把所有有前置任务的任务拉回最早合法日期。

负浮动时间是什么意思?

最晚开始落在最早开始之前,通常是因为指定的交付期早于逻辑允许的最早完工日。−4 不是富余,它表示这件事本该四天前就开始。gantts.app 把浮动时间小于或等于零的任务都标为关键,所以负浮动会显示出来而不是被抹掉。

本文也提供英文版本。

免费创建你的甘特图

在浏览器中直接使用,无需注册。数据保存在你自己的设备上。

打开编辑器