(1)AOV网(Activity On Vertex Network)
AOV网是一个表示工程的有向图中,其中的顶点用来表示活动,弧则用来表示活动之间的优先关系。举个简单的例子,假定起床后可以边煮水,边刷牙洗脸,但洗脸要在刷牙后,煮好水,刷好牙洗好脸以后,就可以喝水了,这个活动的AOV图如下(其中的每个顶点都表示一个活动,而顶点之间的弧表示了活动之间的执行先后顺序):
(2)AOE网( Activity On Edge Network)
AOE网是一个表示工程的带权有向图,其中的顶点用来表示某个事件,弧用来表示活动,弧上的权值用来表示活动持续的时间。例如上述例子的AOE网如下:
(3)AOE网和AOV网的区别
AOV网:其顶点用来表示活动。AOE网是用来表示活动之间的制约关系。
AOE网:顶点表示事件,边表示活动,边上的权值用来表示活动持续的时间。AOV网是用来分析工程至少需要花多少时间完成,或是为了缩短时间需要加快哪些活动等问题。
(4)源点、汇点、路径长度
在AOE网中,
始点或源点:入度为0的顶点,它表示一个工程的开始;
终点或汇点:出度为0的顶点,它表示一个工程的结束;
路径长度:路径上各个活动所持续的时间之和。
(5)关键路径、关键活动
在AOE网中,从源点到汇点具有最大长度的路径称为关键路径,在关键路径上的活动称为关键活动。
(1)要找出一个AOE网中的关键路径,就要先找出网里的关键活动,这些关键活动间的路径就是关键路径。
(2)判断一个活动是不是关键活动,方法是要先找到所有活动的最早开始时间和最晚开始时间,并且对它们进行比较,如果二者相等(意味着这个活动在该工程中没有时间松动),说明这个活动是关键活动。
(3)对于活动
注意,这里假设顶点下标从0开始,所以Vi==0,则表示它是源点,因此最早的开始时间为0;当某个顶点不是源点,那么只有在它前面的事件都发生完后,才能轮到这个事件,所以用了max。
(4)对于活动
(1)数据结构
typedef struct EdgeListNode{ //边表结点
int adjId;
int weight;
EdgeListNode* next;
};
typedef struct VertexListNode{ //顶点表结点
int in; //入度
int data;
EdgeListNode* firstadj; //指向其边表
};
typedef struct GraphAdjList{ //图结构
int vertexnumber; //顶点个数
int edgenumber;
VertexListNode vertextlist[Maximum];
};
(2)具体实现
1)由基本思路可以知道,要求一个AOE网的关键路径,步骤如下:
A. 首先初始化每个顶点的最早开始为0,然后对AOE网进行拓扑排序,在排序的过程中获取每个顶点的最早开始时间;
B. 获取拓扑排序后,初始化每个顶点的最晚开始时间为汇点的最早开始时间,并从AOE网的汇点开始,从后往前,对每个顶点找到求其最晚开始时间;
C. 遍历图中的每条边(方法是遍历图中每个顶点的边表),求其最早开始时间和最晚开始时间,如果二者相等,则这是个关键活动,将其加入关键路径中。
2)代码
#include
#include
#include
#include
int main() {
GraphAdjList g;
EdgeListNode *e;
int i, j, k;
g.vertexnumber = 5;
g.edgenumber = 7;
for(i=1; i<=g.vertexnumber; i++) {
g.vertextlist[i].data = i;
g.vertextlist[i].firstadj = NULL;
}
g.vertextlist[1].in = 0;
g.vertextlist[2].in = 1;
g.vertextlist[3].in = 2;
g.vertextlist[4].in = 2;
g.vertextlist[5].in = 1;
e = (EdgeListNode*)malloc(sizeof(EdgeListNode));
e->adjId = 2; e->weight = 2; e->next = g.vertextlist[1].firstadj; g.vertextlist[1].firstadj = e;
e = (EdgeListNode*)malloc(sizeof(EdgeListNode));
e->adjId = 4; e->weight = 1; e->next = g.vertextlist[1].firstadj; g.vertextlist[1].firstadj = e;
e = (EdgeListNode*)malloc(sizeof(EdgeListNode));
e->adjId = 5; e->weight = 1; e->next = g.vertextlist[1].firstadj; g.vertextlist[1].firstadj = e;
e = (EdgeListNode*)malloc(sizeof(EdgeListNode));
e->adjId = 3; e->weight = 3; e->next = g.vertextlist[2].firstadj; g.vertextlist[2].firstadj = e;
e = (EdgeListNode*)malloc(sizeof(EdgeListNode));
e->adjId = 4; e->weight = 5; e->next = g.vertextlist[2].firstadj; g.vertextlist[2].firstadj = e;
e = (EdgeListNode*)malloc(sizeof(EdgeListNode));
e->adjId = 3; e->weight = 8; e->next = g.vertextlist[4].firstadj; g.vertextlist[4].firstadj = e;
e = (EdgeListNode*)malloc(sizeof(EdgeListNode));
e->adjId = 3; e->weight = 1; e->next = g.vertextlist[5].firstadj; g.vertextlist[5].firstadj = e;
vectorans;
ans = CriticalPath(g);
for(i=0; i"<