AOE网的关键路径练习

难度:@

迁移度:@

关键路径是AOE网中那些改变后会影响整个流程完成时间的路径。

那么核心思想就是将路径目标点的最迟完成时间减去出发点的最早完成时间计算出“富裕时间”如果富裕时间是零,那么路径一定是关键路径。

为了计算,首先要建立两个表格,存储每个点的最迟完成时间和最早完成时间。

为了建立这两个表格以及之后的计算,要建立点的邻接表(adjacency list):取图中每个顶点成表,每个顶点又包含所有指向自己的路径和从自己出发的路径。

在此之前,先要有一张图,这个代码就是通过txt文件读入图的信息,按照:顶点 目标 权重 目标 权重 ...的方式读入。

输入例如:

\\ver.txt\\

0 1 6 2 4 3 5
1 4 1
2 4 1
3 5 2
4 7 7 6 9
5 7 4
6 8 2
7 8 4
8

输出的关键路径:

0>1   1>4   4>6   4>7   6>8   7>8  

细节部分:

FigureIn函数用于建立每个顶点进入该顶点路径的表;

isAOE计算是否是标准的aoe图,换句话说该图不能带环路,否则报错;

MakeActivList通过路径权重建立最早和最晚发生时间两张表;

MakeEventsList通过上述过程计算后将一对出发点和目标点打包储存;

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <map>
#include <forward_list>

struct  ArcNode
{
	int		adjvex;
	int		weight;
};

struct  VertexNode
{
	int		vertex;
	int		outDegree =0;
	int		inDegree =0;
	std::forward_list<ArcNode>		InEdgelist;
	std::forward_list<ArcNode>		Edgelist;
};

class  Adjlist
{
public:
	enum {INF = 0x3f3f3f3f};
	bool		hasInDegree = false;
	
	std::vector<VertexNode>		Vertexlist;
	std::vector<int>		eActivs;
	std::vector<int>		lActivs;
	std::vector<std::pair<int,int>>		CriticalEvents;
public:	
	Adjlist(std::ifstream& file)
	{
		int		aim,weight,vnum;
		std::string		line;
		while (getline(file,line))  {
			std::istringstream		record(line);
			record >> vnum;
			VertexNode		ver{vnum};
			while(record >> aim){
				record >> weight;
				ArcNode		arc{aim,weight};
				(ver.Edgelist).emplace_front(arc);
				ver.outDegree +=1;
			}
			Vertexlist.push_back(ver);
		}
		
	}
public:	
	void FigureIn()
	{
		if(!hasInDegree){
			for (auto vn : Vertexlist){
				for (ArcNode aim : vn.Edgelist){
					ArcNode		arc{vn.vertex,aim.weight};
					Vertexlist[aim.adjvex].InEdgelist.emplace_front(arc);
					Vertexlist[aim.adjvex].inDegree +=1;
				}
			}
			hasInDegree = true;
		}
	}
	
	void PrintGraph()
	{
		if (!hasInDegree) this->FigureIn();
		for (auto Vn : Vertexlist){
			std::cout << '['<< Vn.vertex <<"]...";
			std::cout << '{'<< Vn.outDegree <<'}';
			for (ArcNode a : Vn.Edgelist){
				std::cout << a.adjvex << '('<<a.weight<<')' <<' ';
			}
			std::cout << "  <"<< Vn.inDegree <<'>';	
			for (ArcNode a : Vn.InEdgelist){
				std::cout << a.adjvex << '('<<a.weight<<')' <<' ';
			}
			std::cout << '\n';	
		}	
	}

	bool isAOE()
	{
		
		if (!hasInDegree) this->FigureIn();
		bool		keepOn;
		int		count = Vertexlist.size();
		std::vector<VertexNode>		VertexlistCopy(Vertexlist);
		do{
			keepOn = false;
			for (VertexNode& vn : VertexlistCopy){
				if (vn.inDegree == 0){
					vn.inDegree -=1;
					keepOn = true;
					for (ArcNode& arc : vn.Edgelist){
						VertexlistCopy[arc.adjvex].inDegree -=1;	
					}
					count -=1;
				}
			}	
		}while(keepOn);	
		return   count == 0 ? true : false;
	}

	void MakeActivsList()
	{
		if (this->isAOE()){
			int		count = Vertexlist.size();
			eActivs = std::vector<int>(count, 0);
			lActivs = std::vector<int>(count, INF);	
			std::vector<VertexNode>		VertexlistCopy(Vertexlist);
			while (count > 0){
				for (auto& vn : VertexlistCopy){
					if (vn.inDegree == 0){	
						count -=1;
						for (auto& arc :vn.Edgelist){
							VertexlistCopy[arc.adjvex].inDegree -=1;
							if (arc.weight + eActivs[vn.vertex] > eActivs[arc.adjvex]){
								eActivs[arc.adjvex] = arc.weight + eActivs[vn.vertex];
							}
						}
						vn.inDegree -=1;
					}
				}
			}
			count = Vertexlist.size();
			while (count > 0){
				for (auto& vn : VertexlistCopy){
					if (vn.outDegree == 0){	
						count -=1;
						if (vn.Edgelist.empty())  lActivs[vn.vertex] = eActivs[vn.vertex];
						for (auto& arc : vn.InEdgelist){
							VertexlistCopy[arc.adjvex].outDegree -=1;
							if (lActivs[vn.vertex] - arc.weight < lActivs[arc.adjvex]){
								lActivs[arc.adjvex] = lActivs[vn.vertex] - arc.weight;
							}
							
						}
						vn.outDegree -=1;
					}
				}
			}

		}else std::cout << "not AOE";
	}
	void MakeeEventsList() 
	{
		this->MakeActivsList();
		for (const auto& vn : Vertexlist){
			for (const auto& arc : vn.Edgelist){
				if (eActivs[vn.vertex] == lActivs[arc.adjvex] - arc.weight){
					std::cout << vn.vertex << ">"<< arc.adjvex <<"   ";
					CriticalEvents.emplace_back(std::pair<int,int>(vn.vertex,arc.adjvex));
				}
			}
		}
	}
};



int main()
{
	std::ifstream		f_in("vet.txt");
	Adjlist		july(f_in);

	july.MakeeEventsList();
	f_in.close();
	return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值