与AOE有关的研究问题
◆ 完成整个工程至少需要多少时间?
◆ 哪些活动是影响工程进度(费用)的关键?
工程完成最短时间:从起点到终点的最长路径长度(路径上各活动持续时间之和) 。长度最长的路径称为关键路径,关键路径上的活动称为关键活动。关键活动是影响整个工程的关键。
设v0是起点,从v0到vi的最长路径长度称为事件vi的最早发生时间,即是以vi为尾的所有活动的最早发生时间。
若活动ai是弧<j, k>,持续时间是dut(<j, k>),设:
◆ e(i):表示活动ai的最早开始时间;
◆ l(i):在不影响进度的前提下,表示活动ai的最晚开始时间; 则l(i)-e(i)表示活动ai的时间余量,若l(i)-e(i)=0,表示活动ai是关键活动。
◆ ve(i):表示事件vi的最早发生时间,即从起点到顶点vi的最长路径长度;
◆ vl(i):表示事件vi的最晚发生时间。则有以下关系:
含义是:源点事件的最早发生时间设为0;除源点外,只有进入顶点vj的所有弧所代表的活动全部结束后,事件vj才能发生。即只有vj的所有前驱事件vi的最早发生时间ve(i)计算出来后,才能计算ve(j) 。
方法是:对所有事件进行拓扑排序,然后依次按拓扑顺序计算每个事件的最早发生时间。
含义是:只有vj的所有后继事件vk的最晚发生时间vl(k)计算出来后,才能计算vl(j) 。
方法是:按拓扑排序的逆顺序,依次计算每个事件的最晚发生时间。
求AOE中关键路径和关键活动
⑴ 算法思想
① 利用拓扑排序求出AOE网的一个拓扑序列;
② 从拓扑排序的序列的第一个顶点(源点)开始,按拓扑顺序依次计算每个事件的最早发生时间ve(i) ;
③ 从拓扑排序的序列的最后一个顶点(汇点)开始,按逆拓扑顺序依次计算每个事件的最晚发生时间vl(i) ;
对于图7-24的AOE网,处理过程如下:
◆ 拓扑排序的序列是: (v0, v1, v2, v3 , v4, v5 , v6 , v7 , v8)
◆ 根据计算ve(i)的公式(7-2)和计算vl(i)的公式(7-3) ,计算各个事件的ve(i)和vl(i)值,如表7-2所示。
◆ 根据关键路径的定义,知该AOE网的关键路径是: (v0, v2, v4, v7 , v8) 和(v0, v2, v5 , v7 , v8) 。
◆ 关键路径活动是:<v0, v2>,<v2, v4>,<v2, v5>,<v4, v7>,<v5, v7>,<v5, v8> 。
算法实现
void critical_path(ALGraph *G)
{
int j, k, m ;
LinkNode *p ;
if (Topologic_Sort(G)==-1)
printf(“\nAOE网中存在回路,错误!!\n\n”) ;
else
{
for ( j=0; j<G->vexnum; j++)
ve[j]=0 ; /* 事件最早发生时间初始化 */
for (m=0 ; m<G->vexnum; m++)
{
j=topol[m] ;
p=G->adjlist[j].firstarc ;
for (; p!=NULL; p=p->nextarc )
{
k=p->adjvex ;
if (ve[j]+p->weight>ve[k])
ve[k]=ve[j]+p->weight ;
}
} /* 计算每个事件的最早发生时间ve值 */
for ( j=0; j<G->vexnum; j++)
vl[j]=ve[j] ; /* 事件最晚发生时间初始化 */
for (m=G->vexnum-1; m>=0; m--)
{
j=topol[m] ;
p=G->adjlist[j].firstarc ;
for (; p!=NULL; p=p->nextarc )
{
k=p->adjvex ;
if (vl[k]-p->weight<vl[j])
vl[j]=vl[k]-p->weight ;
}
} /* 计算每个事件的最晚发生时间vl值 */
for (m=0 ; m<G->vexnum; m++)
{
p=G->adjlist[m].firstarc ;
for (; p!=NULL; p=p->nextarc )
{
k=p->adjvex ;
if ( (ve[m]+p->weight)==vl[k])
printf(“<%d, %d>, m, j”) ;
}
} /* 输出所有的关键活动 */
} /* end of else */
}
算法分析
设AOE网有n个事件,e个活动,则算法的主要执行是:
◆ 进行拓扑排序:时间复杂度是O(n+e) ;
◆ 求每个事件的ve值和vl值:时间复杂度是O(n+e) ;
◆ 根据ve值和vl值找关键活动:时间复杂度是O(n+e) ;
因此,整个算法的时间复杂度是O(n+e) 。