有向无环图—关键路径详解(最通俗易懂的版本)【数据结构】

文章目录

  • 有向无环图
    • 拓扑排序
    • AOV-网
    • AOE-网
      • 关键路径的概念
      • 事件的最早/晚开始时间
      • 事件和活动的区分
      • 活动的最早/晚开始时间

有向无环图

有向无环图—关键路径详解(最通俗易懂的版本)【数据结构】_第1张图片

拓扑排序

有向无环图—关键路径详解(最通俗易懂的版本)【数据结构】_第2张图片

AOV-网

有向无环图—关键路径详解(最通俗易懂的版本)【数据结构】_第3张图片
由于有向无环图可以用一种自然的方式对优先关系或依赖关系进行描述,因此在工程计划与管理方面有广泛而重要的应用。一个大的工程往往可以分解为若干相对独立的子工程(活动),子工程之间在进行的时间上有一定的相互制约关系。将这些子工程之间的先后关系用有向图表示,其中顶点表示活动,有向边表示活动之间的优先制约关系,称这种有向图为顶点表示活动的网,简称AOV网。

AOE-网

有向无环图—关键路径详解(最通俗易懂的版本)【数据结构】_第4张图片

表示一个实际工程计划的AOE网应当是无环且存在唯一的源点和汇点的。如果途中存在多个入度为0的顶点,那么可以添加一个虚拟源点,使这个虚拟源点到原来各个入度为0的顶点都有一条权值为0的边。对多个出度为0的顶点的情况可做类似的处理。
(这里其实不是很懂)

关键路径的概念

有向无环图—关键路径详解(最通俗易懂的版本)【数据结构】_第5张图片
有向无环图—关键路径详解(最通俗易懂的版本)【数据结构】_第6张图片

在AOE网中有些活动可以并行地进行。因此,完成整个工程的最短时间应该是从源点到汇点的最长路径的长度(路径长度等于路径上各边权值之和)。

需要注意的是:AOE网中可能有不止一条的关键路径

分析关键路径的目的是找出关键活动,即不按期完成就会影响整个工程的完成时间的活动,从而为决策者提供调度依据。应当投入较多的人力和物力在关键活动上,以保证整个工程按期完成,并可争取提前完成。

有向无环图—关键路径详解(最通俗易懂的版本)【数据结构】_第7张图片
由于关键路径由关键活动组成,因此只要找出AOE网中的关键活动,就可以找到关键路径。

有向无环图—关键路径详解(最通俗易懂的版本)【数据结构】_第8张图片
有向无环图—关键路径详解(最通俗易懂的版本)【数据结构】_第9张图片
(这里看不懂可以看下面)

事件是有向图中的顶点。活动的最早开始时间和最晚开始时间可以直接由事件的最早开始时间和最晚开始时间求得。因此,算法的核心在于求事件的最早开始事件和最晚开始时间。

由活动和事件的关系可知:求解过程有正推和反推两个过程:先正推,才能找到耗时最长的路径;再反推,就可找出关键活动(即l(ai)=e(ai)的活动);由关键活动就找到了关键路径

有向无环图—关键路径详解(最通俗易懂的版本)【数据结构】_第10张图片
求解步骤:

  1. 求拓扑排序
  2. 从始点v0出发,令ve[0]=0,按拓扑有序求ve[j](对j来说,取所有进来的边的最大值:ve(j)=Max{ve(i)+dut()})
  3. 从终点vn-1出发,令vl[n-1]=ve[n-1],按逆拓扑有序求vl[i](对j来说,取所有出去的边的最小值:vl(i)=Min{vl(j)-dut()})
  4. 根据各顶点的ve和vl值,求每条弧(活动)aj的最早开始时间e[aj]和最迟开始时间l[aj]。e(aj)=ve(j); l(aj)=vl(k)-dut() j—aj-k
  5. 如果e[aj]=l[aj],则ai为关键活动

事件的最早/晚开始时间

好了看到这里你会说这说的什么玩意 , 下面我用人话解释一下:
事件(顶点)的最早开始时间:
某个顶点的最早开始时间就是指这个工程最早什么时候能开工?也就是所有的前置工程什么时候完成了,就可以开工了。也就是所有前置工程的最早的开工时间,再加上那个工程所需的时间中,最大的值,(这样才能保证所有前置工程都开工了。)

选取所有前置工程的最早开始时间加上工程时间的最大值,这就是最早开始时间。

事件(顶点)的最晚开始时间:
比如我不想那么早开干,能拖一天是一天 ,但是要保证不会影响后面的工程,那么此时就是找到后一个工程的最晚开始时间,(也就是后一个懒狗 ),意思就是我再懒再拖,也不能影响我后面的懒狗导致他不能及时开工。
比如同学A交给我一个任务,我做完后要交给他继续完成,他最晚5号要开始做,那我要做两天的话,那我最晚3号就要交给他。
多人运动的情况就是:
比如同学AB交给我一个任务,我做完后要交给他们继续完成,同学A最晚5号要开始做,那我要做两天的话,那我最晚3号就要交给他,但是同学B最晚4号要开始做,那我只能2号就开始做了。

所以选取所有后置工程的最晚开始时间减去工程时间的最小值就是我的最晚开始时间了

事实上当一个顶点连了多个边的时候,当到达了最晚开始时间,事实上这个顶点所指向的所有边中,可能并不是所有边都必须得立马开工的,有些边也还是可以继续偷懒的,只要让最紧迫的那个边开工就行了,其他的边是存在冗余时间的

而最晚开始时间减去最早开始时间等于冗余时间。
但是需要注意一点,初始的顶点和最后一个顶点,由于大家所有人都希望工程尽早完工,所以不会给最开始的点和最后的点偷懒的机会,也就意味着没有冗余时间。(最前面和最后面的顶点注定做不了懒狗

所以最早的顶点和最晚的顶点他们的最晚开始时间只能等于最早开始时间。

事件和活动的区分

这里要注意区分上面和下面的情况:

一个顶点是一个事件,一条边是一个活动。或者可以这么说,这样可能更好理解,在游戏里,一个公会有很多玩家,一个公会达成一个称号,或者取得某个成就,或者建房子(也就是事件),他需要各个玩家去做事才能完成。当A玩家和B玩家都达成了“取得排名第一”的成就时,公会就达成了“有两个玩家达成第一”的成就。
所以事件和活动是这样的一个关系。

一个事件需要一些活动来作为前置,那些活动完成之后,事件(成就)才可以达成。而达成了这个成就后,就可以再安排公会里的其他成员去做其他事情来达成新的成就。

因此一个事件连着多个活动,有前置活动和后置活动,而一个活动只连接了两个顶点。

由于一个顶点(一个成就)涉及到多个活动(各个玩家的努力),因此需要在多个活动直接选择最值。
但是活动只涉及到两个顶点的事,不需要考虑最值。

活动的最早/晚开始时间

活动(边)的最早开始时间
一个事件什么时候可以开始,或者说一个成就什么时候达成之后,就可以开始做“因为有了这个成就就可以做新的事”这样的事情了。

所以活动的最早开始事件等于事件的最早开始时间。意思就是某个成就达成后就可以做新的活动了。

活动(边)的最晚开始时间
这里需要注意,一个活动(边)的最晚开始时间并不是顶点的最晚开始时间,这是因为一个顶点需要考虑多个活动,让多个活动都不能延误,因此顶点需要在所有活动的最晚开始时间中选择最早的那个。而一个活动只需要考虑本身就行了。
因此活动的最晚开始时间等于其所指向的那个点的最晚时间减去工程的长度

有向无环图—关键路径详解(最通俗易懂的版本)【数据结构】_第11张图片
有向无环图—关键路径详解(最通俗易懂的版本)【数据结构】_第12张图片
然后我们找到冗余时间为零的点连起来即为关键路径:
有向无环图—关键路径详解(最通俗易懂的版本)【数据结构】_第13张图片
其次要注意:

若AOE网中有多条关键路径,那么仅提高一条关键路径上的关键活动的速度并不能导致整个工程缩短工期,而必须提高同时在几条关键路径上的关键活动的速度才能有效

你可能感兴趣的:(c++编程相关,数据结构,算法)