关键路径
利用AOV网络,对其进行拓扑排序能对工程中活动的先后顺序作出安排。但一个活动的完成总需要一定的时间,为了能估算出某个活动的开始时间,找出那些影响工程完成时间的最主要的活动,我们可以利用带权的有向网,图中的边表示活动,边上的权表示完成该活动所需要的时间,一条边的两个顶点分别表示活动的开始事件和结束事件,这种用边表示活动的网络,称为“AOE网”。
其中,有两个特殊的顶点(事件),分别称为源点和汇点,源点表示整个工程的开始,通常令第一个事件(事件1)作为源点,它只有出边没有入边;汇点表示整个工程的结束,通常令最后一个事件(事件n)作为汇点,它只有入边没有出边;其余事件的编号为2到n-1。
在实际应用中,AOE网应该是没有回路的,并且存在唯一的入度为0的源点和唯一的出度为0的汇点。
下图表示一个具有12个活动的AOE网。图中有8个顶点,分别表示事件0到7,其中,0表示开始事件,7表示结束事件,边上的权表示完成该活动所需要的时间。
下面先讨论一个事件的最早发生时间和一个活动的最早开始时间。如下图,事件Vj必须在它的所有入边活动eik(1≤k≤n)都完成后才能发生。活动eik(1≤k≤n)的最早开始时间是与它对应的起点事件Vik的最早发生时间。所有以事件Vj为起点事件的出边活动ejk(1≤k≤m)的最早开始时间都等于事件Vj的最早发生时间。所以,我们可以从源点出发按照上述方法,求出所有事件的最早发生时间。
设数组earliest[1…n]表示所有事件的最早发生时间,则我们可以按照拓扑顺序依次计算出earliest[k]:
earliest[1]=0
earliest[k]=max{earliest[j]+dut[j][k]}
(其中,事件j是事件k的直接前驱事件,dut[j][k]表示边<j,k>上的权)
对于上图,用上述方法求earliest[0…7]的过程如下:
earliest[0]=0
earliest[1]=earliest[0]+dut[0][1]=0+6=6
earliest[2]=earliest[0]+dut[0][2]=0+7=7
earliest[4]=max{earliest[1]+dut[1][4],earliest[2]+dut[2][4]}
=max{6+5,7+4}
=11
earliest[3]=max{earliest[1]+dut[1][3],earliest[4]+dut[4][3]}
=max{6+3,11+3}
=14
earliest[5]=max{earliest[3]+dut[3][5],earliest[4]+dut[4][5]}
=max{14+2,11+4}
=16
earliest[6]=earliest[4]+dut[4][6]=11+3=14
earliest[7]=max{earliest[3]+dut[3][7],earliest[5]+dut[5][7], earliest[6]+dut[6][7]}
=max{14+5,16+2,14+4}
=19
最后得到的earliest[7]就是汇点的最早发生时间,从而可知整个工程至少需要19天完成。
但是,在不影响整个工程按时完成的前提下,一些事件可以不在最早发生时间发生,而向后推迟一段时间,我们把事件最晚必须发生的时间称为该事件的最迟发生时间。同样,有些活动也可以推迟一段时间完成而不影响整个工程的完成,我们把活动最晚必须开始的时间称为该活动的最迟开始时间。一个事件在最迟发生时间内仍没发生,或一个活动在最迟开始时间内仍没开始,则必然会影响整个工程的按时完成。事件Vj的最迟发生时间应该为:它的所有直接后继事件Vjk(1≤k≤m)的最迟发生时间减去相应边<Vj,Vjk>上的权(活动ejk需要时间),取其中的最小值。且汇点的最迟发生时间就是它的最早发生时间,再按照逆拓扑顺序依次计算出所有事件的最迟发生时间,设用数组lastest[1…n]表示,即:
lastest[n]=earliest[n]
lastest[j]=min{lastest[k]-dut[j][k]}
(其中,事件k是事件j的直接后继事件,dut[j,k]表示边<j,k>上的权)
对于上图,用上述方法求lastest [0…7]的过程如下:
lastest[7]=earliest[7]=19
lastest[6]=lastest[7]-dut[6][7]=19-4=15
lastest[5]=lastest[7]-dut[5][7]=19-2=17
lastest[3]=min{lastest[5]-dut[3][5],lastest[7]-dut[3][7]}
=min{17-2,19-5}
=14
lastest[4]=min{lastest[3]-dut[4][3],lastest[5]-dut[4][5], lastest[6]-dut[4][6]}
=min{14-3,17-4,15-3}
=11
lastest[2]=lastest[4]-dut[2][4]=11-4=7
lastest[1]=min{lastest[3]-dut[1][3],lastest[4]-dut[1][4]}
=min{14-3,11-5}
=6
lastest[0]=min{lastest[1]-dut[0][1],lastest[2]-dut[0][2]}
=min{6-6,7-7}
=0
计算好每个事件的最早和最迟发生时间后,我们可以很容易地算出每个活动的最早和最迟开始时间,假设分别用actearliest和actlastest数组表示,设活动i的两端事件分别为事件j和事件k,如下所示:
活动i
事件j ————————> 事件k
则:actearliest[i]=earliest[j]
actlastest[i]=lastest[k]-dut[j][k]
余量(称为开始时间余量)是该活动的最迟开始时间减去最早开始时间,余量不等于0的活动表示该活动不一定要在最早开始时间时就进行,可以拖延一定的余量时间再进行,也不会影响整个工程的完成。而余量等于0的活动必须在最早开始时间时进行,而且在规定的工期内完成,否则将影响整个工程的完成。
我们把开始时间余量为0的活动称为“关键活动”,由关键活动所形成的从源点到汇点的每一条路径称为“关键路径”。