关键路径与AOE网

        在一个表示工程的带权有向图中,用顶点表示事件,用有向边表示活动,用边上的权值表示活动的持续时间,这种有向图的边表示活动的网,我们叫做AOE网(Activity On Edge Network)。AOE网中没有入度的顶点称为源点或始点,没有出度的顶点称为终点。AOE网是要建立在活动之间制约关系没有矛盾的基础之上,再来分析完成整个工程至少需要多少时间。

        我们把路径上各个活动所持续的时间之和叫做路径长度,从源点到终点具有最大长度的路径叫做关键路径,在关键路径上的活动叫关键活动。我们找到所有活动的最早开始时间和最晚开始时间,如果它们相等,则此活动是关键活动,活动间的路径为关键路径。如果不相等,则就不是。


       我们定义一下四个参数:

               1.事件的最早发生时间 etv,即顶点Vk的最早发生时间;

               2.事件的最晚发生时间 ltv,即顶点Vk的最晚发生时间;

               3.活动的最早开工时间 ete,边Ak的最早发生时间;

               4.活动的最早开工时间 lte,边Ak的最晚发生时间;

       我们由1和2可以求得3和4,然后在根据 ete 和 lte 是否相等来判断活动k是否为关键活动。

     

      求事件的最早发生时间 etv[i] 的过程,就是从头到尾找拓扑序列的过程,因此,在求关键路径之前,需要先调用一次拓扑序列算法的代码来计算 etv[i] 和拓扑序列列表。

代码如下:

//边表结点
typedef struct EdgeNode  
{
	int adjvex;//邻接点域,存储该顶点对应的下标
	int weight;//存储权值
	struct EdgeNode * next;
}EdgeNode;

//顶点表结构
typedef struct VertexNode 
{
	int in;//顶点入度
	int data;//顶点域,存储顶点信息
	EdgeNode * firstedge;//边表头指针
}VertexNode;

typedef struct  GraphAdjList
{
	VertexNode adjList[MAXVEX];
	int vertexNum;
}GraphAdjList;

int etv[VERTEX],ltv[VERTEX];//事件最早发生时间和最晚发生时间
int stack2[VERTEX];//用于存储拓扑序列的栈
int top2;//指向stack2的栈顶

void TopologicalSort(GraphAdjList GL)
{
	EdgeNode * e;
	int i,k,gettop;
	int top = -1;//指向栈顶
	int count = 0;//统计输出顶点的个数
	int stack[MAXVEX];//用栈来存储入度为0的顶点

	for (i = 0; i < GL.vertexNum; i++)
		if (GL.adjList[i].in == 0)
			stack[++top] = i;//将入度为0的顶点入栈
	top2 = -1;
	for (i = 0; i < GL.vertexNum; i++)
		etv[i] = 0;//初始化为0

	while (top != -1)
	{
		gettop = stack[top--];//出栈
		count++;
		stack2[++top2] = gettop;//将弹出的顶点序号压入拓扑序列的栈
		e = GL.adjList[gettop].firstedge;
		while (e != NULL)//遍历此顶点的弧表
		{
			k = e->adjvex;
			if (!(--GL.adjList[k].in))//入度为0则入栈
				stack[++top] = k;
			if ((etv[gettop] + e->weight) > etv[k])//求各顶点事件最早发生时间值
				etv[k] = etv[gettop] + e->weight;
			e = e->next;
		}
	}
	if (count < GL.vertexNum)
		printf("有回路");
}

void CriticalPath(GraphAdjList GL)
{
	EdgeNode * e;
	int i,gettop,k,j;
	int ete,lte;//声明活动最早发生时间和最迟发生时间
	TopologicalSort(GL);	//求拓扑序列,计算数组etv和stack2的值
	for (i = 0; i < GL.vertexNum; i++)
		ltv[i] = etv[GL.vertexNum - 1];//初始化ltv
	while (top2 != -1)//计算ltv
	{
		gettop = stack2[top2--];//将拓扑序列出栈,后进先出
		e = GL.adjList[gettop].firstedge;
		while (e != NULL)
		{//求各顶点事件的最迟发生时间ltv
			k = e->adjvex;
			if (ltv[k] - e->weight < ltv[gettop])
				ltv[gettop] = ltv[k] - e->weight;
			e = e->next;
		}
	}
	for (j = 0; j < GL.vertexNum; j++)
	{
		e = GL.adjList[j].firstedge;
		while (e != NULL)
		{
			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);
			e = e->next;
		}
	}
}
可以结合下图分析:



  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值