关键路径(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;
}

  

上一篇:vue项目用antv/g6做网络拓扑图


下一篇:Leetcode 797. 所有可能的路径(中等)