图的关键路径
来源:互联网 发布:软件随想录 txt 编辑:程序博客网 时间:2024/05/17 07:37
转自:
http://blog.sina.com.cn/s/blog_51b6521b0100k96i.html
(一) AOE网
事件
事实上,某结点代表的事件是它的各入边代表的活动的共同作用结果,同时也是它的各出边代表的活动的启动条件。AOE网中没有入边的结点称为始点,没有出边的结点称为终点。AOE一般用来描述工程进度,结点表示工程进展中的状态,边表示子任务。图 21‑4就是一个AOE网,它可以看作是一个具有11项子任务和9个状态的假想工程的进度图。
(二) AOE网的操作
(三) 关键路径的若干基本概念
下面的阐述中,设AOE网的起点为v0终点为vn.
1.关键路径
AOE网中,从事件i到j的路径中,加权长度最大者称为i到j的关键路径(Critical Path),记为cp(i,j)。特别地,始点0到终点n的关键路径cp(0,n)是整个AOE的关键路径。
显然,关键路径决定着AOE网的工期,关键路径的长度就是AOE网代表的工程所需的最小工期。
2.事件最早/晚发生时间
事件vi的最早发生时间ve(i)定义为:从始点到vi的最长(加权)路径长度,即cp(0,i)
事件vi的最晚发生时间vl(i)定义为:在不拖延整个工期的条件下,vi的可能的最晚发生时间。即vl(i) = ve(n) - cp(i, n)
3.活动最早/晚开始时间
活动ak=<vi, vj>的最早开始时间e(k):等于事件vi的最早发生时间,即
活动ak=<vi, vj>的最晚开始时间l(k)定义为:在不拖延整个工期的条件下,该活动的允许的最迟开始时间,即
这里,vl(j)是事件j的允许的最晚发生时间,len(i, j)是ak的权。
活动ak的最大可利用时间:定义为l(k)-e(k)
若活动ak的最大可利用时间等于0(即(l(k)=e(k)),则称ak 为关键活动,否则为非关键活动。
显然,关键活动的延期,会使整个工程延期。但非关键活动不然,只要它的延期量不超过它的最大可利用时间,就不会影响整个工期。
关键路径的概念,也可以用这里的关键活动定义,即有下面的:
(一) 基本算法
根据前面给出的定义,可推出活动的最早及最晚发生时间的计算方法:
结点的最早发生时间的计算,需按拓扑次序递推:
对所有<i,j> ∈E的i
关于
这种计算方法, 依赖于拓扑排序, 即计算ve( j) 前,应已求得j 的各前趋结点的ve值,而计算vl(i)前,应已求得i的各后继结点的vl值。ve的计算可在拓扑排序过程中进行,即在每输出一个结点i后,在删除i的每个出边<i,j>(即入度减1)的同时,执行
实际上,该操作对i的每个后继j分别进行一次。因此对程序作少量扩充即可求得ve。
vl的值可按类似的方法在逆拓扑排序过程(即直接按与拓扑序列相反的次序输出结点的过程)中求得,但一般不必专门这样进行。事实上,通过逆方向使用拓扑序列即可递推出各vl的值,假定拓扑序列是topoSeq,则vl 的值的求法为(结点编号为1~n)。
for (k=1; k<=n; k++) vl[k] = ve[n]; //初始化 for ( k=n; k>=1; k--) { i=topoSeq[k]; j=(i的第1个出点); while (j存在) { if (vl[j]-len(i,j)<vl[i]) vl[i]=vl[j]-len(i,j); j = (i的下一个出点); } }
求图21-6 的AOE网的所有事件的最早发生时间ee();所有事件的最迟发生时间le();每项活动ai的最早开始时间e()和最迟开始时间l(),完成此工程最少需要多少天?那些是关键活动,是否存在某项活动,当其提高速度后能使整个工程缩短工期?
存储结构及算法设计
1、在结点的定义中增加ee和le 字段用于记录个事件的最早开始时间和最迟开始时间,同时得到关键路径和最小工期
2、邻接矩阵中使用边权代替原来连接标志1
3、进行拓扑排序,形成拓扑序列
1 2 3 4 5 6 7 8 9
4、按拓扑序列顺序,从前向后搜索寻找个活动(即边),若存在该活动,则计算相应事件的最早开始时间。
5、按拓扑序列顺序,从后向前搜索寻找个活动(即边),若存在该活动,则计算相应事件的最迟开始时间。
6、计算各活动的最早开始时间和最迟开始时间
算法源程序:
#include <stdio.h>#include <stdlib.h>#define MaxVerNum 20 int visited[MaxVerNum]; typedef char VertexType; typedef struct ArcNode{ int adjvex; //该弧指向的顶点位置 struct ArcNode * nextarc; //指向下一个表结点 int info; //权值信息}ArcNode; //边结点类型 typedef struct VNode{ VertexType data; int indegree; ArcNode * firstarc;}VNode, Adjlist[MaxVerNum]; typedef struct{ Adjlist vertices; //邻接表 int vernum, arcnum; //顶点数和弧数}ALGraph; //查找符合的数据在数组中的下标int LocateVer(ALGraph G, char u){ int i; for(i = 0; i < G.vernum; i++) { if(u == G.vertices[i].data) return i; } if(i == G.vernum) { printf("Error u!\n"); exit(1); } return 0;} //常见图的邻接矩阵void CreateALGraph(ALGraph &G){ int i, j, k, w; char v1, v2; ArcNode * p; printf("输入顶点数和弧数: "); scanf("%d %d", &G.vernum, &G.arcnum); printf("请输入顶点!\n"); for(i = 0; i < G.vernum; i++) { printf("请输入第 %d 个顶点: \n", i); fflush(stdin); scanf("%c", &G.vertices[i].data); G.vertices[i].firstarc = NULL; G.vertices[i].indegree = 0; } for(k = 0; k < G.arcnum; k++) { printf("请输入弧的顶点和相应权值(v1, v2, w): \n"); //清空输入缓冲区 fflush(stdin); scanf("%c %c %d", &v1, &v2, &w); i = LocateVer(G, v1); j = LocateVer(G, v2); p = (ArcNode *)malloc(sizeof(ArcNode)); p->adjvex = j; p->info = w; p->nextarc = G.vertices[i].firstarc; G.vertices[i].firstarc = p; G.vertices[j].indegree++; //vi->vj, vj入度加1 } return;} //求图的关键路径函数void CriticalPath(ALGraph G){ int i, k, e, l; int * Ve, * Vl; ArcNode * p; //***************************************** //以下是求时间最早发生时间 //***************************************** Ve = new int [G.vernum]; Vl = new int [G.vernum]; for(i = 0; i < G.vernum; i++) //前推 Ve[i] = 0; for(i = 0; i < G.vernum; i++) { ArcNode * p = G.vertices[i].firstarc; while(p != NULL) { k = p->adjvex; if(Ve[i] + p->info > Ve[k]) Ve[k] = Ve[i]+p->info; p = p->nextarc; } } //***************************************** //以下是求最迟发生时间 //***************************************** for(i = 0; i < G.vernum; i++) Vl[i] = Ve[G.vernum-1]; for(i = G.vernum-2; i >= 0; i--) //后推 { p = G.vertices[i].firstarc; while(p != NULL) { k = p->adjvex; if(Vl[k] - p->info < Vl[i]) Vl[i] = Vl[k] - p->info; p = p->nextarc; } } //****************************************** for(i = 0; i < G.vernum; i++) { p = G.vertices[i].firstarc; while(p != NULL) { k = p->adjvex; e = Ve[i]; //最早开始时间为时间vi的最早发生时间 l = Vl[k] - p->info; //最迟开始时间 char tag = (e == l) ? '*' : ' '; //关键活动 printf("(%c, %c), e = %2d, l = %2d, %c\n", G.vertices[i].data, G.vertices[k].data, e, l, tag); p = p->nextarc; } } delete [] Ve; delete [] Vl;} void main(){ ALGraph G; printf("以下是查找图的关键路径的程序。\n"); CreateALGraph(G); CriticalPath(G);}
- 图的关键路径
- 图的关键路径
- 图的关键路径
- 图的关键路径
- 图的关键路径
- 图的关键路径
- 图的关键路径
- 图的关键路径算法
- AOE图的关键路径
- 求图的关键路径
- 图的关键路径的实现
- 图的C++关键路径代码
- 图的拓扑排序与关键路径
- 带树有向图的关键路径
- 关键路径和前导图的计算
- 有向图的关键路径
- 图的关键路径与拓扑排序
- 算法:图的关键路径-数据结构(24)
- Ubuntu10.04 下设定 TFTP 服务
- 如何解决:ERROR: the user data image is used by another emulator. aborting 的问题
- 一些比较重要的数据(方便查阅)
- 搭建 Openfire3.7.0 时遇到的一些问题
- Chrome浏览器下调试flex项目时出现安全沙箱冲突的问题
- 图的关键路径
- [Adobe开发者中心]一周学习Flex4视频中文版(正式版)
- 2011-8-4 21:25:15
- Python Unicode与中文处理
- C++_静态成员
- android:layout_width和android:width的区别
- CCSpriteBatchNode
- 学习笔记—多线程同步与互斥
- ZOJ 2388 Beat the Spread!