有向无环图的应用——关键路径

目录

一、什么是AOE网?

1.1 AOE网的定义和性质

1.2 AOE网的应用

二、什么是关键路径?

2.1 关键路径和关键活动的定义

2.2 寻找关键活动

2.2.1  事件的最早发生时间ve[i]

2.2.2  事件的最晚发生时间vl[i]

2.2.3  活动的最早开始时间ee[i] 

2.2.4  活动的最晚开始时间el[i]  

三、关键路径算法实现

3.1 修改拓扑排序算法

3.2 关键路径算法


一、什么是AOE网?

1.1 AOE网的定义和性质

AOE网:在一个表示工程的带权有向图中,用顶点表示事件,用有向边表示活动,边上的权值表示活动的持续时间,称这样的有向图为边表示活动的网(activity on edge network),简称AOE网。

在AOE网中存在唯一的、入度为0的顶点,称为源点;存在唯一的、出度为0的顶点,称为汇点

AOE网的性质:

  • 只有某顶点所代表的的事件发生后,从该顶点出发的各活动才能开始;
  • 只有在进入某顶点的各活动都结束后,该顶点所代表的事件才能发生。

AOE网示例:

 

1.2 AOE网的应用

AOE网可以回答下列问题:

  • 完成整个工程至少需要多少时间?
  • 为缩短完成工程所需的时间,应当加快哪些活动?

至少需要多少时间才能使事件V4发生?

由图可知,必须在完成活动a1、a2、a4、a5后才能使事件V4发生。完成a1和a4总共需要的时间为7,完成a2和a5总共需要的时间为5。因此,至少需要7时间才能使事件V4发生。

得出结论:

  • 最短工期应该是最长路径;
  • 加快最长路径上的活动就能缩短最短工期。

 


二、什么是关键路径?

2.1 关键路径和关键活动的定义

关键路径:在AOE网中,从源点到汇点具有最大路径长度(该路径上的各个活动所持续的时间之和)的路径称为关键路径。

关键活动:关键路径上的活动称为关键路径。

关键路径可能不只一条,重要的是找到关键活动。

 

2.2 寻找关键活动

要找出关键路径,必须找出关键活动,即不按期完成就会影响整个工程进度的活动。

首先计算以下与关键活动有关的量:

  • 事件的最早发生时间 ve[i];
  • 事件的最晚发生时间 vl[i];
  • 活动的最早开始时间 ee[i];
  • 活动的最晚开始时间 el[i]。

最后计算各个活动的时间余量 el[i] - ee[i],时间余量为0者即为关键活动。

 

2.2.1  事件的最早发生时间ve[i]

计算下图所有事件的最早发生时间:

 

2.2.2  事件的最晚发生时间vl[i]

计算下图所有事件的最晚发生时间:

 

2.2.3  活动的最早开始时间ee[i] 

计算下图所有活动的最早开始时间:

 

 

2.2.4  活动的最晚开始时间el[i]  

计算下图所有活动的最晚开始时间:  

 


三、关键路径算法实现

3.1 修改拓扑排序算法

修改后的拓扑排序算法便于同时求出每个事件的最早发生时间。

/* 求入度函数 */
void FindID(AdjList *G, int indegree[]) {
    int i;
    ArcNode *p;

    for (i = 0; i < G->vexnum; ++i)
        indegree[i] = 0;

    for (i = 0; i < G->vexnum; ++i) {
        p = G->vertex[i].firstarc;
        while (p != NULL) {
            ++indegree[p->adjvex];
            p = p->nextarc;
        }
    }
}

int ve[MAX_VERTEX_NUM];

/* 修改后的拓扑排序算法 */
bool TopoOrder(AdjList *G, Stack *T) {
    int count, i, j, k;
    ArcNode *p;
    int indegree[MAX_VERTEX_NUM];
    Stack *S;

    InitStack(&S);
    FindID(G, indegree);

    for (i = 0; i < G->vexnum; ++i)
        if (indegree[i] == 0)
            Push(S, i);

    count = 0;
    for (i = 0; i < G->vexnum; ++i)
        ve[i] = 0;

    while (!IsEmpty(S)) {
        Pop(S, &j);
        Push(T, j); /* 生成逆拓扑序列 */
        ++count;

        p = G->vertex[j].firstarc;
        while (p != NULL) {
            k = p->adjvex;
            if (--indegree[k] == 0)
                Push(S, k);
            /* 计算最早发生时间 */
            if (ve[j] + p->info.weight > ve[k])
                ve[k] = ve[j] + p->info.weight;

            p = p->nextarc;
        }
    }
    ClearStack(S);

    return count >= G->vexnum;
}

 

3.2 关键路径算法

bool CriticalPath(AdjList *G) {
    ArcNode *p;
    int i, j, k, dut, ei, li;
    char tag;
    int vl[MAX_VERTEX_NUM];
    Stack *T;

    InitStack(&T);
    if (!TopoOrder(G, T)) /* 检验TopoOrder是否执行成功 */
        return false;

    /* 初始化事件的最晚发生时间 */
    for (i = 0; i < G->vexnum; ++i)
        vl[i] = ve[G->vexnum - 1];

    /* 按逆拓扑序列求各顶点的vl值 */
    while (!IsEmpty(T)) {        
        Pop(T, &j);
        p = G->vertex[j].firstarc;
        while (p != NULL) {
            k = p->adjvex;
            dut = p->info.weight;
            if (vl[k] - dut < vl[j])
                vl[j] = vl[k] - dut;

            p = p->nextarc;
        }
    }

    /* 求ee、el,并且输出路径 */
    for (j = 0; j < G->vexnum; ++j) { 
        p = G->vertex[j].firstarc;
        while (p != NULL) {
            k = p->adjvex;
            dut = p->info.weight;
            ee = ve[j];
            el = vl[k] - dut;

            /* 标出关键活动并打印路径 */
            tag = (ee == el) ? '*' : ' ';
            printf("%s,%s,%d,%d,%d,%c\n", Vertex2Name(G->vertex[j].data),         
            Vertex2Name(G->vertex[k].data), dut, ee, el, tag);

            p = p->nextarc;
        }
    }
    ClearStack(T);

    return true;
}
  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对任意给定的(顶点数不小于20,边数不少于30,的类型可以是有向、无向、有向网、无向网),能够输入的顶点和边(或弧)的信息,并存储到相应存储结构(邻接矩阵、邻接表、十字链表、邻接多重表,任选其中两种类型),对自己所创建的完成以下操作: 1、 对无向求每个顶点的度,或对有向求每个顶点的入度和出度(5分) 2、 完成插入顶点和边(或弧)的功能(5分) 3、 完成删除顶点和边(或弧)的功能(5分) 4、 两种存储结构的转换(5分),如果其中一种存储结构为十字链表或邻接多重表则增加5分。 5、 输出的深度优先遍历序列或广度优先遍历序列(5分) 6、 求的深度优先或广度优先的生成树(或生成森林)(存储结构为孩子-兄弟链表),并对生成树进行遍历(15分) 7、 判断的连通性,输出连通分量的个数(5分) 8、 判断中是否存在,无向5分,有向10分 9、 给出顶点u和v,判断u到v是否存在路径(5分) 10、求顶点u到v的一条简单路径(10分) 11、求顶点u到v的所有简单路径(15分) 12、求顶点u到v的最短路径(10分) 13、求顶点u到其余各顶点的最短路径(15分) 14、求任两个顶点之间的最短路径(15分) 15、求最小生成树(15分) 16、对于有一个源点和一个汇点的有向网,求关键路径(20分)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值