关键路径(AOE)
关键路径AOE网的构造,需要拓扑排序作为基础
/*
-------------------------------------------------
Author: wry
date: 2022/2/27 11:10
Description: AOE
-------------------------------------------------
*/
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 1000+10;
struct Edge {
int to;
int length;
Edge(int t,int l):to(t),length(l){}
};
vector<Edge> graph[MAXN];
int inDegree[MAXN];
int earliest[MAXN]; //每个点的点(事件)的最早开始时间
int lastest[MAXN]; //每个点(事件)的最晚开始时间
void AOE(int n) { //输入结点(事件)数
vector<int> dga; //拓扑序列
priority_queue<int,vector<int>,greater<int>> node;
//第一轮将入度为0的点加入待处理序列
for (int i=0;i<n;i++) {
if (inDegree[i]==0) {
node.push(i);
earliest[i] = 1; //源点最早开始时间为1
}
}
//对每个待处理结点处理其指向的点,生成拓扑排序列表,生成每个结点(事件)的最早开始事件
while (!node.empty()) {
int u = node.top();
node.pop();
dga.push_back(u); //加入拓扑序列
for (int i=0;i<graph[u].size();i++) {
int v = graph[u][i].to;
int l = graph[u][i].length;
inDegree[v]--;
if (inDegree[v]==0) {
node.push(v);
}
earliest[v] = max(earliest[u]+l,earliest[v]);
}
}
//根据拓扑排序列表,找到每个结点(事件)的最迟开始时间
for(int i=dga.size()-1;i>=0;i--) { //逆序输出,先输出终点
int u = dga[i];
if (graph[u].size()==0) { //如果此点的出度为0
lastest[u] = earliest[u]; //则表示事件最早开始时间和最晚开始时间相同
}
else {
lastest[u] = INT_MAX; //如何出度不是0,则表示有多个分支,现在不应该处理它,取INT_MAX,方便后面使用min函数;
}
//对于出度不为0的结点而言,需要利用其指向的结点,计算其最迟开始时间
for (int j=0;j<graph[u].size();j++) {
int v = graph[u][j].to;
int l = graph[u][j].length;
lastest[u] = min(lastest[u],lastest[v]-l);
}
}
}
int main() {
int n,m; //n个结点,m条边
while (cin>>n>>m) {
//初始化操作
memset(graph,0,sizeof(graph));
memset(inDegree,0,sizeof(inDegree));
memset(earliest,0,sizeof(earliest));
memset(lastest,0,sizeof(lastest));
//构造图
while (m--) {
int from,to,length;
cin >> from >> to >> length;
graph[from].push_back(Edge(to,length));
inDegree[to]++;
}
//生成拓扑序列、事件最早开始时间、最晚开始时间
AOE(n);
//关键路径长度,即为出度为0的结点(终点)的最早完成时间的最大值
int answer=0;
for (int i=0;i<n;i++) {
answer = max(answer,earliest[i]);
}
cout << answer << endl;
}
return 0;
}