图的关键路径

1、概念

活动的网(AOE):在一个表示工程的带权有向图中,用顶点表示事件,用有向边表示活动,用边上的权值表示活动的持续时间,这种有向图的边表示活动的网,我们称之为AOE网(Activity On Edge Network)。

AOE网具有以下两个性质:

①只有在某顶点所代表的事件发生后,从该顶点出发的各有向边所代表的活动才能开始。

②只有在进入一某顶点的各有向边所代表的活动都已经结束,该顶点所代表的事件才能发生。

源点/始点:AOE网中没有入边的顶点。

汇点/终点:没有出边的顶点。

关键路径:我们把路径上各个活动所持续的时间之和称为路径长度,从源点到汇点具有最大长度的路径叫关键路径。

关键活动:在关键路径上的活动叫关键活动。

2、应用范围

如果用AOE网来表示一项工程,那么,仅仅考虑各个子工程之间的优先关系还不够,更多的是关心整个工程完成的最短时间是多少;哪些活动的延期将会影响整个工程的进度,而加速这些活动是否会提高整个工程的效率。因此,通常在AOE网中列出完成预定工程计划所需要进行的活动,每个活动计划完成的时间,要发生哪些事件以及这些事件与活动之间的关系,从而可以确定该项工程是否可行,估算工程完成的时间以及确定哪些活动是影响工程进度的关键。

3、条件

图使邻接表存储。

4、code

int *etv,*ltv;    /*事件最早发生时间和最迟发生时间数组*/
int *stack2;    /*用于存储拓扑序列的栈*/
int top2;    /*用于stack2的指针*/

/*拓扑排序,用于关键路径计算*/
/*行18~22、27、33~34是对拓扑排序算法的增加*/
Status TopologicalSort(GraphAdjList GL)
{
    EdgeNode *e;
    int i,k ,gettop;
    int top=0;    /*用于栈指针下标*/
    int count=0;    /*用于统计输出顶点的个数*/
    int *stack;    /*建栈将入度为0的顶点入栈*/
    stack=(int *)malloc(GL->numVertexes * sizeof(int));
    for(i=0;i<GL->numVertexes;i++)
        if(0==GL->adjList[i].in)
            stack[++top]=i;
    top2=0;    /*初始化为0*/
    etv=(int *)malloc(GL->numVertexes * sizeof(int));    /*事件最早发生时间*/
    for(i=0;i<GL->numVertexes;i++)
        etv[i]=0;    /*初始化为0*/
    stack2=(int *)malloc(GL->numVertexes * sizeof(int));    /*初始化*/
    while(top!=0)
    {
        gettop=stack[top--];
        count++;
        stack2[++top2]=gettop;    /*将弹出的顶点序号亚如拓扑序列的栈*/
        for(e=GL->adjList[gettop].firstedge;e;e=e->next)
        {
            k=e->adjvex;
            if(!(--GL->adjList[k].in))
                stack[++top]=k;
            if((etv[gettop]+e->weight)>etv[k])    /*求各顶点事件最早发生时间值*/
                etv[k]=etv[gettop]+e->weight;}
    }
    if(count<GL->numVertexes)
        return ERROR;
    else
        return OK;
}

/*求关键路径,GL为有向网,输出GL的各项关键活动*/
void CriticalPath(GraphAdjList GL)
{
    EdgeNode *e;
    int i,gettop,k,j;
    int ete,lte;    /*声明活动最早发生时间和最迟发生时间变量*/
    TopologicalSort(GL);    /*求拓扑序列,计算数组etv和stack2的值*/
    ltv=(int *)malloc(GL->numVertexes*sizeof(int));    /*事件最晚发生的时间*/
    for(i=0;i<GL->numVertexes;i++)
        ltv[i]=etv[GL->numVertexes-1];    /*初始化ltv*/
    while(top2!=0)
    {
        gettop=stack2[top2--];
        for(e=GL->adjList[gettop].firstedge;e;e=e->next)
        {
            /*求各顶点事件的最迟发生时间ltv值*/
            k=e->adjvex;
            if(ltv[k]-e->weight<ltv[gettop])    /*求各顶点事件最晚发生时间ltv*/
                ltv[gettop]=ltv[k]-e->weight;
        }
    }
    /*求ete,lte和关键活动*/
    for(j=0;j<GL->numVertexes;j++)
    {
        for(e=GL->adjList[j].firstedge;e;e=e->next)
        {
            k=e->adjvex;
            ete=etv[j];    /*活动最早发生时间*/
            lte=ltv[k]-e->weight;    /*活动最迟发生时间*/
            if(ete==lte)    /*两者相等即在关键路径上*/
                printf("<v%d,v%d> lenght:%d,",GL->adjList[j].data,GL->adjList[k].data,e->weight);
        }
    }
}

你可能感兴趣的:(关键路径)