关键路径

本文详细介绍了关键路径的概念,包括AOE网、始点、终点等,并通过实例解析了关键路径的计算方法,包括事件的最早发生时间、最迟发生时间、活动的最早开始时间和最迟开始时间。此外,还提供了关键路径的代码实现,展示了如何在有向图中找到关键路径。最后指出,一个AOE网可能存在多条关键路径。
摘要由CSDN通过智能技术生成

关键路径

1.相关概念

AOE网

  • AOE网:在一个表示工程的带权有向图中,用顶点表示事件(如V0),用有向边表示**活动(如<v0,v1> = a1),**边上的权值表示活动的持续时间,称这样的有向图为边表示的活动的网,简称AOE网(activity on edge network)

  • 始点(源点):AOE网中没有入边的顶点,如顶点V0

  • 终点(汇点):没有出边的顶点,如顶点V3

2. 比较

在这里插入图片描述
深红色便是关键路径
在这里插入图片描述

3. 性质

①只有在进入某顶点的活动都已经结束,该顶点所代表的事件才发生。例如:a1和a2活动都结束了,顶点V2所代表的事件才会发生。

②只有在某顶点所代表的事件发生后,从该顶点出发的各活动才开始。例如:只有顶点V1所代表的事件结束之后,活动a2和a4才会开始。

4.关键路径部分解析

  • 在AOE网中,所有活动都完成才能到达终点,因此完成整个工程所必须花费的时间(即最短工期)应该为源点到终点的最大路径长度。具有最大路径长度的路径称为关键路径

  • 关键路径上的活动称为关键活动
    在这里插入图片描述

  • 事件的最早发生时间:ve[k]。根据AOE网的性质,只有进入Vk的所有活动<Vj, Vk>都结束,Vk代表的事件才能发生,而活动<Vj, Vk>的最早结束时间为ve[j]+len<Vj, Vk>。所以,计算Vk的最早发生时间的方法为:ve[0] = 0,ve[k] = max(ve[j] + len<Vj, Vk>)

  • 事件的最迟发生时间:vl[k]。vl[k]是指在不推迟整个工期的前提下,事件Vk允许的最迟发生时间。根据AOE网的性质,只有顶点Vk代表的事件发生,从Vk出发的活动<Vk, Vj>才能开始,而活动<Vk, Vj>的最晚开始时间为vl[j] - len<Vk, Vj>。

  • 活动的最早发生时间:ee[i]。ai由有向边<Vk, Vj>,根据AOE网的性质,只有顶点Vk代表的事件发生,活动ai才能开始,即活动ai的最早开始时间等于事件Vk的最早开始时间。

在这里插入图片描述

  • 活动的最迟发生时间:el[i]。el[i]是指在不推迟真个工期的前提下,活动ai必须开始的最晚时间。若活动ai由有向边<Vk, Vj>表示,则ai的最晚开始时间要保证事件vj的最迟发生时间不拖后。

在这里插入图片描述

  • 案例:

    AOE网

    事件的最早发生时间:ve[k]

    从源点向终点方向计算

    ve[0] = 0

    ve[1] = ve[0] + a0 = 0 + 4 = 4

    ve[2] = max( ve[0] + a1, ve[1] + a2 ) = max(0 + 3, 4 + 2 = 6

    ve[3] = max(ve[1] + a4, ve[2] + a3) = max(4 + 6, 3 + 4) = 10

    事件的最迟发生时间:vl[k]

    从终点向源点方向计算

    vl[3] = ve[3] = 10

    vl[2] = vl[3] - a3 = 10 - 4 = 6

    vl[1] = min(vl[3] - a4, vl[2] - a2) = min(10-6, 6-2) = 4

    vl[0] = min(vl[2] - a1, vl[1] - a0) = min(4-4, 4-2) = 0

    活动的最早发生时间:ee[i]

    共有五个活动:

    ee[0] = ve[0] = 0

    ee[1] = ve[0] = 0

    ee[2] = ve[1] = 4

    ee[3] = ve[2] = 6

    ee[4] = ve[1] = 4

    活动的最迟发生时间:el[i]

    el[0] = v[1] - a0 = 4 - 4 = 0

    el[1] = vl[2] - a1 = 6 - 3 = 3

    el[2] = vl[2] - a2 = 6 - 2 = 4

    el[3] = vl[3] - a3 = 10 - 4 = 6

    el[4] = vl[3] - a4 = 10 - 6 = 4

    活动的最早开始时间和最晚开始时间相等,则说明该活动时属于关键路径上的活动,即关键活动。

    经过比较,得出关键活动有:a0, a2, a3, a4,画出示意图如下:

    关键路径图

    该AOE网有两条关键路径。

    所以,通过此案例也可以发现,一个AOE网的关键路径可能有多条
    再举个例子
    在这里插入图片描述
    在这里插入图片描述
    etv可以推出ete ltv可以简单换算出lte:这个点的事件最晚发生时间-弧活动的最晚发生时间
    关键路径就是ete == lte

5.代码

在之前拓扑序列算法上进行修改

int *etv, *ltv;
int *stack2; //用于存储拓扑序列的栈
int top2; //用于stack2的栈顶指针

//改进后的求拓扑序列的算法
Status TopologicalSort(GraphAdjList GL)
{
    EdgeNode *e;
    int i, k, gettop;
    int top = 0;
    int count = 0;
    int *stack;
    stack = (int *)malloc(sizeof(int) * Gl -> numVertexes);
    for(i = 0; i < GL -> numVertexes; i++)
    {
        if(0 == Gl -> adjList[i].in)
        {
            stack[++top] = i;
        }
    }
    top2 = 0;
    etv = (int *)malloc(GL -> numVertexes *sizeof(int));
    for(i = 0; i < GL-> numVertexes; i++)
    {
        etv[i] = 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都为汇点的时间
    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)
        {
            k = e -> adjvex;
            if(ltv[k] - e -> weight < ltv[gettop])
            {
                ltv[gettop] = ltv[k] - e -> weight;
            }
        }
    }
    //通过etv和ltv求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> length: %d", GL -> adjList[j].data, GL -> adjList[k].data, e -> weight);
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值