关键路径算法(Critical Path)

这个算法《算法导论》中并没有提及,很多书和博客说的有点奇怪,所以写本文作为笔记。

关键路径是什么

关键路径的定义非常简单:就是一个图中,权值之和最大的路径就是关键路径。

那么就可以知道关键路径不唯一

为什么有关键路径

关键路径的来源和拓扑排序是一样的,都是将一项较大的工程划分为多个子工程,然后表示子工程之间的关系的。

关键路径和拓扑排序不同之处在于:

  • 拓扑排序强调子工程之间的先后顺序(说依赖关系可能更恰当一些),比如必须做完a才能做c
  • 关键路径在拓扑排序的基础上,还加入了时间关系。这个时间关系不光是子工程之间的,也包括子工程和整体之间的。

比如必须做完ab才能做c,做完cd才能做e,而a需要 3 天,b需要 5 天,c需要 1 天,d需要 4 天。

  • 那么整体上来说,
    • c必须要等五天后才可以开始做,这个 5 天有个术语叫c最早发生时间,也就是c最快要什么时候开始。 d最早发生时间0,因为没有前置事件,同理ab也是 0。
    • d最快可以一开始就做,因为没有前置事件,但是最晚开始的时间,只能推迟一天,不然加上做的 4 天,1+4=5,会导致c做完了,d还没做完,就会耽误e的发生。而这个 1 天的术语叫做最迟发生时间,也就是d最晚要什么时候开始。
    • 需要注意这里的时间由于是从0开始的,等五天后得到的是2+3=5,相当于第六天开始,写算法的时候要注意这点。

  • 局部来说,a可以延期 2 天再开始,d可以延期 1 天,也都不会耽误进度。在关键路径中,这个可以延期的时间也有个术语叫做时间余量。可以看到就是最迟发生时间 - 最早发生时间,或者说结束时间-(最早结束时间-子工程耗时),明白含义之后,公式和变形就很好记了。

当然稍微复杂一些的最迟发生时间就很难简单看出来了,因为前置条件太复杂,所以要有个计算流程,避免人为出错。

如何求得关键路径

求关键路径的方法很多书上说的很难似的,其实很简单。以下图为例:

请添加图片描述

源点(开始的点)选择是V1

AOE 关键路径图中,顶点是子工程的开始,边是事件。箭头可以理解为时间的发展方向。这与拓扑排序不同。

第一步:求子工程之间的关系和最早发生时间

关键路径的来源和拓扑排序是一样的,第一步当然是先找到子工程之间的依赖关系,在这个过程中,可以顺道加上路径的权值(在上面的例子中,也就是天数)。

那么可以得到一个序列和每个节点的最早开始时间 V e ( i ) V_e(i) Ve(i)。也就是路径权值相加最大值,具体来说,就是多个前驱的时候选最早开始时间+权值最大的一个,刚好与最短路径算法相反:

V 1 V_1 V1 V 2 V_2 V2 V 3 V_3 V3 V 4 V_4 V4 V 5 V_5 V5 V 6 V_6 V6
V e ( i ) V_e(i) Ve(i)032668

下标e表示early,早嘛。

第二步:求子工程最迟发生时间(逆拓扑排序)

拓扑排序是先从无前驱的节点开始(没有前置条件),然后删点删边,一次次后得到序列。而逆拓扑排序是从无后继节点开始(不会影响其他节点)。

这里概念听上去就很乱,但是实际上你可以重现画一个图,前驱改后继,后继改前驱(箭头取反),然后从得到的最大值(这里是8)进行拓扑排序和记录时间(加变减),得到的结果一样的,远比书上的方法简单快速,不易出错。

如果你看不到下面的,就按照上面的说法,自己拿草稿纸画一下,立马就懂了。

那么可以得到一个序列和对应的最迟开始时间 V l ( i ) V_l(i) Vl(i)。具体每步就是从尾部开始,每个节点的最迟开始时间 V l ( i ) V_l(i) Vl(i)上一个节点的最后开始时间 - 前驱的最小权值

上面得到的最早开始时间序列为:

V 1 V_1 V1 V 2 V_2 V2 V 3 V_3 V3 V 4 V_4 V4 V 5 V_5 V5 V 6 V_6 V6
V e ( i ) V_e(i) Ve(i)032668

最后一个节点的最迟开始时间和最早开始时间一样:

V 1 V_1 V1 V 2 V_2 V2 V 3 V_3 V3 V 4 V_4 V4 V 5 V_5 V5 V 6 V_6 V6
V e ( i ) V_e(i) Ve(i)032668
V l ( i ) V_l(i) Vl(i)8

V 6 V_6 V6逆拓扑排序消除 V 4 V_4 V4 V 5 V_5 V5对应的权值为21(就一个,不分大小了就)。8减去可得:

V 1 V_1 V1 V 2 V_2 V2 V 3 V_3 V3 V 4 V_4 V4 V 5 V_5 V5 V 6 V_6 V6
V e ( i ) V_e(i) Ve(i)032668
V l ( i ) V_l(i) Vl(i)678

然后逆拓扑排序 V 2 V_2 V2 V 3 V_3 V3,要求节点最晚发生时间-权值最小,那么对应最小权值为24(都从 V 4 V_4 V4),6减去这两个值可得:

这里是为了说明,实际上算出来直接选就行了,“最小权值”不需要求出来

V 1 V_1 V1 V 2 V_2 V2 V 3 V_3 V3 V 4 V_4 V4 V 5 V_5 V5 V 6 V_6 V6
V e ( i ) V_e(i) Ve(i)032668
V l ( i ) V_l(i) Vl(i)42678

最后减去最小后继权值2(从 V 3 V_3 V3),2减去这个值可得:

V 1 V_1 V1 V 2 V_2 V2 V 3 V_3 V3 V 4 V_4 V4 V 5 V_5 V5 V 6 V_6 V6
V e ( i ) V_e(i) Ve(i)032668
V l ( i ) V_l(i) Vl(i)042678

第三步:作差得到时间余量,为0的就是关键节点,组成关键路径

V 1 V_1 V1 V 2 V_2 V2 V 3 V_3 V3 V 4 V_4 V4 V 5 V_5 V5 V 6 V_6 V6
V e ( i ) V_e(i) Ve(i)032668
V l ( i ) V_l(i) Vl(i)042678
V l ( i ) − V e ( i ) V_l(i)-V_e(i) Vl(i)Ve(i)010010

那么关键路径就为: V 1 − > V 3 − > V 4 − > V 6 V_1 -> V_3 -> V_4 -> V_6 V1>V3>V4>V6。很多图的关键路径不能这么算,因为可能有多个路径的权值之和都是最大值,也就是说有多个关键路径,那么就要自己看一下图了,选一个好算的。(也就是下一节的内容)

快速计算

按照上面的方法很烦,每次计算都要算两个序列,我又不是电脑,算那么多很慢的,所以可以直接找最大后继最小前驱

以 2019 年 408 的一道题来说:找出下面 AOE 网中,活动 d最早开始时间和最晚开始时间。

请添加图片描述

你可以算两个序列,但是那太麻烦了。

开始时间就是前面的节点,也就是2。那就算从12之间最大的路径和最长路径减去26之间的最小路径。

那么眼一打最早开始时间就是12

最晚开始时间可能需要算一下16的最大路径,算出来是27。然后继续用眼一打,26之间的最小路径为13,那么27-13=14。所以最晚开始时间是14

怕看错,就把每个路径写出来,然后选出最大/最小的一个,有些路径大题就是这么答的。

这个原理是关键路径的定义:权值之和最大的路径就是关键路径。所以关键路径不唯一,我们可以利用这一点选一个好算的路径就行了。

关键路径有何用

我们前文说,关键路径表示的是工程所需的最大时间,那么就可以使用关键路径得知如何改进时间。

如果改进一件事的时间,可以让所有关键路径(也就是最大值)减少,那么改进这件事所需的时间,就可以减少整个工程所需的时间。

希望能帮到有需要的人~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/50251.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

安装 moleculeSTM 踩坑日记

“学习 LLM ,在大模型时代为自己存张船票”。 相信很多人都有这样的想法。那么,在 AI for science 领域,哪些 LLM 模型值得一试呢? 笔者认为: LLM 直接预测 SMILES 性质 or 直接生成 SMILES 的技术路线是行不通的。因…

搭建DNS正向解析,反向解析+搭建DNS主从架构+搭建DNS多区域+时间同步

主要在局域网中配置,不存在外网 正向解析:域名解析为IP named.conf 解决权限 named.rfc1912.zones 解决解析方式 环境准备:三台机器都做下面的操作 基础配置:网络配置,关闭安全架构,关闭防火墙&#x…

Redis常用命令第二版

目录 1. 连接 Redis 客户端 1.1 连接实例1: 1.2 连接实例2: 1.3 极速版查看键值命令: 1.4 获取 Redis 配置: 2. 启动 Redis 实例 2.1 启动实例1: 2.2 启动实例2: 2.3 启动253的实例: …

Linux相关指令

1.查看手册 man 3 free 2.调试 ①gcc link.c -g ②gbd a.out ③(gbd)r 运行 ④(gbd)q 退出 3.gcc demo8.c -lpthread -o demo8 //该指令将demo.c生成的a.out文件命名为demo8 。其中的-lpthread不是必须的,只有用到该库才输入加上。 4…/a.out 10 >>test.ret.t…

使用langchain4j调用大模型写个聊天助手

LangChain4j是一款基于Java的高效、灵活的AI大模型应用框架,专为简化Java应用程序与LLMs(大语言模型)的集成而设计。它提供统一API和模块化设计,支持多种LLM提供商和嵌入模型,以及丰富的工具箱,如AI服务和R…

光伏混合储能直流微网直流母线电压下垂控制MATLAB仿真

微❤关注“电气仔推送”获得资料(专享优惠) 模型简介 此模型以混合储能系统为研究对象,采用基于关联参数SOC的改进下垂控制策略,将初始下垂系数与储能单元SOC的n次幂的比值作为现行下垂系数,通过改变n值,…

【快速上手ESP32(ESP-IDF)】ADC数模转换(含单次转换和连续转换以及校准)

这篇为重置版。 因为准备录制视频了,然后回过头看看之前讲ADC的文章发现有不少错误的地方(但是代码是可以用的),而且讲的也不全面,因此决定写下这个重置版。 这边提供三种使用ADC的方法,第一种是老方法&a…

港科夜闻 | 香港科大与阿里巴巴合作,计划成立大数据与人工智能联合实验室

关注并星标 每周阅读港科夜闻 建立新视野 开启新思维 1、香港科大与阿里巴巴合作,计划成立大数据与人工智能联合实验室。香港科大7月19日与阿里巴巴集团签署合作备忘录,计划成立「香港科技大学–阿里巴巴大数据与人工智能联合实验室」,就生成…

科普文:万字梳理31个Kafka问题

1、 kafka 是什么,有什么作用 2、Kafka为什么这么快 3、Kafka架构及名词解释 4、Kafka中的AR、ISR、OSR代表什么 5、HW、LEO代表什么 6、ISR收缩性 7、kafka follower如何与leader同步数据 8、Zookeeper 在 Kafka 中的作用(早期) 9、Kafka如何快…

frameworks 之BInder启动

frameworks 之BInder启动 调用 AppRuntime打开驱动 内存映射 ProcessStatePoolThread 开启 Binder 消息 进程在fork 的时候会初始化并启动对应的 Binder。 涉及到的类如下 frameworks/base/core/java/com/android/internal/os/ZygoteInit.javaframeworks/base/core/jni/include…

UDP程序设计

UDP协议概述 UDP,User Datagram Protocol,用户数据报协议,是一个简单的面向数据报(package-oriented)的传输层协议,规范为:RFC 768。 UDP提供数据的不可靠传递,它一旦把应用程序发给网络层的数据发送出去…

Java | Leetcode Java题解之第300题最长递增子序列

题目&#xff1a; 题解&#xff1a; class Solution {public int lengthOfLIS(int[] nums) {int len 1, n nums.length;if (n 0) {return 0;}int[] d new int[n 1];d[len] nums[0];for (int i 1; i < n; i) {if (nums[i] > d[len]) {d[len] nums[i];} else {int…

做一个能和你互动玩耍的智能机器人之四--固件

在openbot的firmware目录下我们能够找到arduino的固件源码和相关的文档。 openbot的controller目录下&#xff0c;是控制器的代码目录&#xff0c;用来控制机器人做一些动作。未来的目标是加入大模型&#xff0c;使其能够理解人的语言和动作来控制。 固件代码&#xff0c;支持…

利用小爱同学与点灯科技+esp8266+舵机,制作智能关灯神器:小白也可制作,米家同步设备可实现多部手机进行控制。(亲测有用)

利用小爱同学与点灯科技&#xff0c;制作智能关灯神器&#xff1a;小白也可制作&#xff0c;米家同步设备可实现多部手机进行控制。 文章目录 利用小爱同学与点灯科技&#xff0c;制作智能关灯神器&#xff1a;小白也可制作&#xff0c;米家同步设备可实现多部手机进行控制。1.…

19. Revit API: Parameter(参数)

一、前言 我们在前面或多或少提到也用到参数了&#xff0c;这篇便细讲一下。 首先&#xff0c;我们知道好多信息都藏在参数里&#xff0c;或者说可以从参数中获取。我们还能够通过调整参数的值&#xff0c;改变模型的形态&#xff0c;即族的参变。 其次&#xff0c;有时族上…

对接支付接口、分账系统、银行云账户如何与我们合作

以下是对接流程的优化版本&#xff0c;以提供更清晰的步骤和描述&#xff1a; 一、签约与打款&#xff1a; 客户完成合同签约。 同时进行首次打款&#xff0c;合同细节可以在后续补充。 二、对接服务专群&#xff1a; 客户与服务专群&#xff08;技术、客服等团队&#xff09;取…

一文讲透如何使用CSS美化HTML界面

上一篇文章(初识HTML文件&#xff0c;创建自己的第一个网页&#xff01;)介绍了HTML文件&#xff0c;并实战练习了如何编写一个结构简单的HTML网页&#xff0c;但最后也提到了单纯使用HTML语言创建的网页并不美观&#xff0c;有没有一个东西像PS能够美化图片一样让我们能够对我…

python 面向对象基础

1.self # 1. 定义类 class Washer (): def wash ( self ): print ( hellow world ) # <__main__.Washer object at 0x0000024BA2B34240> print ( self ) # 2. 创建对象 haier1 Washer () # <__main__.Washer object at 0x0000018B7B224240> print (…

RockyLinux 9.3 安装docker-ce

先安装yum工具 dnf install yum-utils -y

【前端 16】使用Ajax发送异步请求

Ajax 基础入门&#xff1a;实现异步请求 Ajax&#xff08;Asynchronous JavaScript and XML&#xff09;是一种在无需重新加载整个网页的情况下&#xff0c;能够更新部分网页的技术。通过使用 Ajax&#xff0c;可以在后台与服务器交换数据&#xff0c;这意味着可以在不影响用户…