难度:@
迁移度:@
关键路径是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;
}