图——关键路径

 

AOE网示例图:

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

源点:

在AOE网中,没有入边的顶点称为源点;如顶点V0

终点:

在AOE网中,没有出边的顶点称为终点;如顶点V3

AOE网的性质:

【1】只有在进入某顶点的活动都已经结束,该顶点所代表的事件才发生;

         例如:a1和a2活动都结束了,顶点V2所代表的事件才会发生。

【2】只有在某顶点所代表的事件发生后,从该顶点出发的各活动才开始;

         例如:只有顶点V1所代表的事件结束之后,活动a2和a4才会开始。

 

在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网的关键路径可能有多条。

### 关键路径算法及其邻接表表示 #### 关键路径算法概述 关键路径算法用于在络计划技术中找出完成整个工程所需的最短时间。该算法主要应用于有向无环(DAG),其中顶点代表事件,边则代表活动,每条边上附带权重表示完成相应活动所需的时间。 对于DAG中的每一个节点v来说,有两个重要参数:最早发生时间和最迟发生时间。这两个概念帮助计算各个任务之间的浮动时间,并最终确定哪些任务位于项目的最关键路线上[^1]。 #### 邻接表表示法简介 采用邻接表来表达是一种节省空间的有效手段,尤其适合稀疏。具体而言,在C语言里可以通过定义两个数组实现——一个是用来保存各结点信息的一维数组;另一个是由指针构成的链表集合,每个元素对应于某个特定结点所关联的所有其他结点的信息列表。 以下是基于上述描述的一个简单例子: ```c #include <stdio.h> #include <stdlib.h> // 定义单个链接的数据结构体 typedef struct EdgeNode { int adjvex; // 存储弧头的位置编号 float weight; // 边上的权值 struct EdgeNode *next; }EdgeNode; // 定义顶点数据结构体 typedef struct VertexNode { char data; // 顶点信息(这里假设为字符型) EdgeNode *firstedge;// 指向第一条依附该顶点的边的指针 }VertexNode, AdjList[MAX_VERTEX_NUM]; // 创建一个新的边缘节点并返回其地址 EdgeNode* CreateEdge(int vj,float w){ EdgeNode *e=(EdgeNode *)malloc(sizeof(EdgeNode)); e->adjvex=vj; e->weight=w; e->next=NULL; return e; } void AddEdge(AdjList G,int vi,int vj,float w){ EdgeNode *p,*q; p=G[vi].firstedge; if(!p){ // 如果当前顶点还没有任何连接,则直接创建新的边缘节点作为第一个 G[vi].firstedge=CreateEdge(vj,w); }else{ while(p->next!=NULL)p=p->next; // 否则遍历到链表末端再添加新节点 q=CreateEdge(vj,w); p->next=q; } } ``` 此代码片段展示了如何利用邻接表构建加权有向,并提供了一个简单的接口`AddEdge()`用于增加一条从vi指向vj具有指定权重w的新边。
评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值