算法笔记_图算法专题_关键路径 AOV网和AOE网

关键路径

1.基本概念

1.AOV网:顶点活动网,是指用顶点表示活动,而用边集表示活动优先关系的有向无环图。
2.AOE网:边活动网,是指用带权的边集表示活动,而用顶点表示事件的有向无环图。
AOV网和AOE网都不能存在环,否则会出现逻辑错误。

3.一般而言,AOV网(AOE网)只有一个源点和一个汇点,即便存在多个源点或汇点,也可以通过添加超级源点和超级
  汇点来将它变成只含有一个源点和一个汇点的AOV网(AOE网)

4.AOV转换为AOE:
(1)将AOV的每个顶点都拆成两个顶点,分别表示活动的起点和终点,用有向边连接,有向边表示原顶点的活动,
     边权给定。
(2)原AOV网中的边全部视为空活动,边权为05.解决的问题:
	a.工程起始到终止至少需要多少时间
	b.哪条(些)路径上的活动是影响整个工程的进度的关键
  

2.关键路径求法
在这里插入图片描述

在AOE网中求解。

(1)变量说明:
1.e[]:e数组用来表示活动a的最早开始时间
2.l[]:l数组用来表示活动a的最迟开始时间
3.ve[]:表示事件i的最早发生时间
4.vl[]:表示事件i的最迟发生时间

关键活动:关键路径上的活动。e[r]==l[r]表示活动a[r]是关键活动。
关系:e[r] = ve[i]     
	  l[r] = vl[j]-length[r]2)求解每个结点的 ve 和 vl
ve[j] = max{ ve[i1]+length[r1] ~ ve[ik]+length[rk] }:拓扑序
vl[i] = min{ vl[j1]-lenght[r1] ~ vl[jk]-length[rk] }:逆拓扑序

(3)代码实现:
	//拓扑序列
	stack<int> topOrder;
	//拓扑排序,顺便求ve数组
	bool topologicalSort(){
		queue<int> q;
		for(int i=0;i<n;i++){
			if(inDegree[i]==0){
				q.push(i);
			}
		}
		
		while(!q.empty()){
			int u = q.front();
			q.pop();
			topOrder.push(u);
			for(int i=0;i<G[u].size();i++){
				int v = G[u][i].v;
				inDegree[v]--;
				if(inDegree[v]==0){
					q.push(v);
				}
				
				//用ve[u]更新u的所有后继结点v的ve[v]
				if(ve[u]+G[u][i].w>ve[v]){
					ve[v] = ve[u]+G[u][i].w;
				} 
			}
		}
		if(topOrder.size()==n) return true;
		else return false;
	} 
	
	
	//关键路径
	int CriticalPath(){
		memset(ve,0,sizeof(ve));
		if(topologicalSort()==false){
			return -1;//不是有向无环图,返回-1 
		} 
		fill(vl,vl+n,ve[n-1]);//假设n-1为汇点,vl数组初始化
		
		//直接使用topOrder出栈即为逆拓扑序列,求解vl数组
		while(!topOrder.empty()){
			int u = topOrder.top();
			topOrder.pop();
			for(int i=0;i<G[u].size();i++){
				int v = G[u][i].v;
				//用u的所有后继结点v的vl[v]来更新vl[u]
				if(vl[v]-G[u][i].w<vl[u]){
					vl[u] = vl[v]-G[u][i].w;
				} 
			}
		} 
		
		//遍历邻接表的所有边,计算活动的最早开始事件e和最迟开始时间l
		for(int u=0;u<n;u++){
			for(int i=0;i<G[u].size();i++){
				int v = G[u][i].v;
				int w = G[u][i].w;
				
				int e = ve[u];
				int l = vl[v]-w;
				
				if(e==l){
					printf("%d->%d",u,v);//输出关键活动 
				}
			}
		} 
		return ve[n-1];
	} 
如果不确定哪个是汇点,那就取ve数组的最大值,汇点的ve最大。
将以下代码加到上述代码的fill前面。
	int maxlength = 0;
	for(int i=0;i<n;i++){
		if(ve[i]>maxlength){
			maxlength = ve[i];
		}
	}
	fill(vl,vl+n;maxlength);
如果图中有多条关键路径,并且要完整输出所有关键路径,可以将关键活动存下来。方法就是建立一个邻接表,
当确定u->v是关键活动时,将边u->v加入邻接表。最后在用DFS遍历这个图就可以获取所有关键路径。
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值