AOE网与关键路径

如果在有向图中用顶点表示事件,用弧表示活动,用弧上的权表示活动持续时间,称该带权有向图(即有向网)为边表示活动的网(activity on edge network),简称AOE网。

在AOE网中,只有一个顶点代表的事件发生后,从该顶点出发的各个弧所代表的活动才能开始,只有以弧头关联一个顶点的各个弧所代表的活动都已结束,该顶点所代表的事件才能发生。

一项工程可以由若干个子工程活动组成。用AOV网表示这项工程所关心的是各子工程之间的优先次序,即所得到得拓扑有序序列;而用AOE网表示这项工程所关心的是完成整个工程至少需要多少时间,哪些子工程是影响这项工程进度的关键活动,如何加快整个工程的进度等问题。

由于在AOE网中某些活动可以并行进行,所以完成工程的最短时间是从源点到汇点路径的最大长度(指路径上各活动持续时间之和最大,而不是路径上弧的数目最多)。把从源点到汇点路径长度最大的路径称作关键路径(critical path),关键路径上的活动称作关键活动。关键活动的长度是整个工程的最短工期,加快关键活动的完成是加快工程进度缩短工期地关键。

求AOE网关键路径算法的步骤:

(1).输入e条弧,建立AOE网的存储结构。

(2).从源点V1出发,令ve[1]=0;按拓扑有序序列次序求其余各顶点的最早发生时间ve[k](2<=k<=n),ve[k]=max{ve[j]+dut()};如果得到的拓扑有序序列中顶点个数小于网中顶点的个数n,说明网中存在环路,不能求关键路径算法终止,否则执行步骤(3).

(3).从汇点Vn出发,令vl[n]=ve[n],按逆拓扑有序序列求其余各顶点的最迟发生时间vl[k](n-1>=k>=1),vl[k]=min{vl[Vj]-dut()}。

(4).根据各顶点的ve值和vl值,求每条弧的最早开始时间e[s]和最迟开始时间l[s];e[s]等于弧s的弧尾顶点Vk的最早发生时间ve[k],而l[s]等于弧头顶点Vk的最迟发生时间减去弧s的权值;若某条弧s满足e[s]=l[s]则为关键活动,由所有关键活动构成的网的一条或几条关键路径。


int toporder(adjlist g[],int n,sqstack t)//AOE网用带入度域的邻接表g[]存储,算法求n个顶点的最早发生时间ve[](全局变量)
//并在顺序栈t中记录顶点的拓扑有序序列
{
    int i,j,k,m=0,top=0;//定义局部变量并初始化统计变量和链栈指针
    nodetype *p;//定义指向邻接表表结点的指针变量
    for(i=1;i<=n;i++) ve[i]=0;//初始化ve[]
    for(i=1;i<=n;i++)//把入度为0的顶点压入由入度域建立的链栈中
        if(g[i].indegree==0)
        {
            g[i].indegree=top;
            top=i;
        }
    while(top!=0)//当链栈不为空时,拓扑排序过程中计算ve[],并在栈t中记下拓扑序列
    {
        j=top;
        top=g[top].indegree;
        push(t,j);//顶点Vj的序号压入顺序栈t中
        m++;//统计变量m加1
        p=g[j].next;//p指向邻接链表第j个链表的第一个结点
        while(p!=NULL)//处理第j个链表中各顶点
        {
            k=p->adjvex;//k指向表结点
            g[k].indegree--;//第k个顶点的入度减1
            if(g[k].indegree==0)//如果入度为0则压入栈中
            {
                g[k].indegree=top;//Vk的入度域指向原栈顶
                top=k;//栈顶指向Vk
            }
            if(ve[j]+p->data>ve[k])//计算ve[k]
                ve[k]=ve[j]+p->data;
            p=p->next;//p指向第j个链的下一个邻接顶点
        }
    }
    if(m


void criticalpath(adjlist g[],int n)//g[]为带权邻接链表存储的AOE网,n为顶点数,算法输出关键路径上各关键活动
{
    int i,j,k,e,l,dut;//定义局部变量
    sqstack t;//定义顺序栈t
    if(toporder(g,n,t)==0)//如果toporder值为0,打印AOE网有环路
        printf("the AOE network has a cycle\n");
    else//否则无环,计算vl值并求e和l确定活动关键
    {
        for(i=n;i>=1;i--)//初始化vl[]
            vl[i]=ve[n];
        while(empty(t)!=0)//当顺序栈不空时,逐一弹出栈顶元素计算vl[j]
        {
            j=pop(t);//弹出栈顶元素于j
            p=g[j].next;//p指向邻接表中第j个链表
            while(p!=NULL)//当链不空时
            {
                k=p->adjvex;//k指向表结点
                dut=p->data;//弧的权值送dut
                if(vl[k]-dutnext;//p指向第j个链表的下一个邻接点
            }
        }
        for(j=1;j<=n;j++)//求e,l和关键活动
        {
            p=g[j].next;//p指向邻接表中第j个链表的第一个结点
            while(p!=NULL)//处理Vj与第j个链表中各顶点组成的弧
            {
                 k=p->adjvex;//链中顶点的序号送k
                 dut=p->data;//弧的权值送dut中
                 e=ve[j];//e为Vj的最早发生时间
                 l=vl[k]-dut;//l为Vk的最迟发生时间减去弧和权值
                 if(e==l)
                     printf("v%d to v%d:weight is %d\n",j,k,dut);
                p=p->next;//p指向第j个链表的下一个顶点
            }
        }
    }
}//criticalpath end


你可能感兴趣的:(数据结构知识汇总)