【关键路径问题(Critical Path)——图】


AOE网(Activity On Edges)------用边表示活动的网络
1、用一个有向图表示一个工程的各子工程及其相互制约的关系,弧表示活动,权表示活动持续的时间,顶点表示事件(活动的开始或结束时间),称这种有向图为边表示活动的网,简称AOE网。
2、AOE网用来估算工程的完成时间。

一、基本术语

源点:入度为0的顶点(只有一个)
汇点:出度为0的顶点(只有一个)
路径长度:路径上各活动持续时间之和
整个工程完成的时间:从有向图的源点到汇点的最长路径
关键路径:路径长度最长的路径

在这里插入图片描述

在这里插入图片描述

二、如何求关键路径

1、问题分析

在这里插入图片描述

2、求关键路径的步骤

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

三、算法实现

1、算法思想

(1)设每个结点的最早发生时间为0,将入度为0的结点进栈
(2)将栈中入度为0的结点V取出,并压入另一个栈,用于形成逆向拓扑排序的序列
(3)根据邻接表找到结点V的所有的邻接结点,将结点V的最早发生时间+活动的权值 得到的和同邻接结点的原最早发生时间进行比较;如果该值大,则用该值取代原最早发生时间。另外,将这些邻接结点的入度减一。如果某一结点的入度变为0,则进栈。
(4)反复执行2、3;直至栈空为止。

2、算法描述

Status CriticalPath(ALGraph G)
{
	//G为邻接表存储的有向网,输出G的各项关键活动
	if (!TopologicalOrder(G, topo)) return ERROR;
	//调用拓扑排序算法,使拓扑序列保存在topo中,若调用失败,则存在有向环
	n = G.vexnum;			//n为顶点的个数
	for (i = 0;i < n;i++)			//给每个事件的最早发生时间置初值为0
		ve[i] = 0;
	/*按照拓扑次序求每个事件的最早发生时间*/
	for (i = 0;i < n;i++)			//for循环结束才能求得最早发生时间
	{
		k = topo[i];			//取得拓扑序列中的顶点序号k
		p = G.vertices[k].firstarc;			//p指向k的第一个邻接点
		while (p != NULL)			//依次更新k的所有邻接顶点的最早发生时间
		{
			j = p->adjvex;			//j为邻接顶点的序号
			if (ve[j] < ve[k] + p->weight)			//更新顶点j的最早发生时间ve[j]
				ve[j] = ve[k] + p->weight;
			p = p->nextarc;			//p指向k的下一个邻接顶点
		}
	}
	for (i = 0;i < n;i++)			//给每个事件的最迟发生时间置初值为ve[n-1]
		vl[i] = ve[n - 1];
	/*按逆拓扑次序求每个事件的最迟发生时间*/
	for (i = n - 1;i >= 0;i--)
	{
		k = topo[i];			//取得拓扑序列中的顶点序号k
		ArcNode* p = G.vertices[k].firstarc;			//p指向k的第一个邻接顶点
		while (p != NULL)
		{	//根据k的邻接点,更新k的最迟发生时间
			j = p->adjvex;			//j为邻接顶点的序号
			if (vl[k] > vl[j] - p->weight)			//更新顶点k的最迟发生时间vl[k]
				vl[k] = > vl[j] - p->weight;
			p = p->nextarc;			//p指向下一个邻接顶点
		}
	}
	/*判断每一活动是否为关键活动*/
	for (i = 0;i < n;i++)
	{ //每次循环针对vi为活动开始点的所有活动
		p = G.vertices[i].firstarc;			//p指向i的第一个邻接顶点
		while (p != NULL)
		{
			j = p->adjvex;			//j为i的邻接顶点的序号
			e = ve[i];			//计算活动<vi,vj>的最早开始时间
			l = vl[j] - p->weight;			//计算活动<vi,vj>的最迟开始时间
			if (e == l)		//若为关键活动,输出<vi,vj>
				cout << G.vertices[i].data << G.vertices[j].data;
			p = p->nextarc;			//p指向i的下一个邻接顶点
		}
	}
}
评论 136
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FEI..

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值