数据结构之关键路径

1、AOE网

AOE网是⼀个带权的有向无环图,其中顶点表示事件(Event),弧表示活动,权表示活动持续的时间。

2、源点和汇点

AOE网中入度为零的点称为源点,将出度为零的点称为汇点。

3、关键路径

完成工程的最短时间是从源点到汇点的最长路径的长度。路径长度最长的路径就叫做关键路径。

ETV(Earliest Time Of Vertex):事件最早发生时间,就是顶点的最早发生时间。LTV(Latest Time Of Vertex):事件最晚发生时间,就是每个顶点对应的事件最晚需要开始的时间,如果超出此时间将会延误整个工期。ETE(Earliest Time Of Edge):活动的最早开工时间,就是弧的最早发⽣时间。LTE(Lastest Time of Edge):活动的最晚开工时间,就是不推迟工期的最晚开工时间。

4、关键路径算法

关键路径(Critical Path)针对有向无环加权图(AOE网,工程活动网络),是从源点(入度为0)到汇点(出度为0)的最长路径。路径上的活动称为关键活动,关键路径长度决定整个工程的最短完成时间,关键活动延时会直接导致整体工程延时。

步骤1:拓扑排序

对AOE网进行拓扑排序,得到有序节点序列,若图存在环则无关键路径,工程无法正常进行。

步骤2:计算最早发生时间 ve\[\]

vei:节点i(事件)的最早发生时间,从源点正向推导。

公式:源点 vestart = 0;遍历拓扑序列,对当前节点u的所有出边 u→v(权重w),执行 vev = max(vev, veu + w)。

步骤3:计算最晚发生时间 vl\[\]

vli:节点i(事件)的最晚发生时间,不推迟整体工程工期,从汇点逆向推导。

公式:汇点 vlend = veend;逆序遍历拓扑序列,对当前节点v的所有入边 u→v(权重w),执行 vlu = min(vlu, vlv - w)。

步骤4:筛选关键节点与关键路径

若节点满足 vei == vli,该节点为关键节点;由相邻关键节点组成的路径,即为关键路径。

cpp 复制代码
#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;

const int MAXN = 105;
const int INF = 0x3f3f3f3f;

// 邻接表存储: to目标节点, weight边权, next下一条边
struct Edge {
    int to, w;
    Edge(int t, int ww) : to(t), w(ww) {}
};
vector<Edge> adj[MAXN];   // 正向邻接表(拓扑、求ve)
vector<Edge> reverseAdj[MAXN]; // 逆向邻接表(求vl)
int inDegree[MAXN];      // 入度数组
vector<int> topoSeq;     // 存储拓扑排序序列
int ve[MAXN], vl[MAXN];  // 最早、最晚发生时间

// 拓扑排序
bool topoSort(int n) {
    queue<int> q;
    // 初始化入度为0的节点入队
    for (int i = 1; i <= n; i++) {
        if (inDegree[i] == 0)
            q.push(i);
    }

    while (!q.empty()) {
        int u = q.front();
        q.pop();
        topoSeq.push_back(u);
        // 遍历出边,更新后继节点入度
        for (Edge e : adj[u]) {
            int v = e.to;
            inDegree[v]--;
            if (inDegree[v] == 0)
                q.push(v);
        }
    }
    // 拓扑序列长度不等于节点数,说明有环,无关键路径
    return topoSeq.size() == n;
}

// 计算关键路径
void criticalPath(int n) {
    // 1. 初始化ve数组,正向求最早发生时间
    memset(ve, 0, sizeof(ve));
    for (int u : topoSeq) {
        for (Edge e : adj[u]) {
            int v = e.to, w = e.w;
            if (ve[v] < ve[u] + w) {
                ve[v] = ve[u] + w;
            }
        }
    }

    // 2. 初始化vl数组,逆向求最晚发生时间
    int endNode = topoSeq.back();
    fill(vl, vl + n + 1, INF);
    vl[endNode] = ve[endNode];
    // 逆序遍历拓扑序列
    for (int i = topoSeq.size() - 1; i >= 0; i--) {
        int v = topoSeq[i];
        for (Edge e : reverseAdj[v]) {
            int u = e.to, w = e.w;
            if (vl[u] > vl[v] - w) {
                vl[u] = vl[v] - w;
            }
        }
    }

    // 3. 输出关键节点和关键路径
    cout << "===== 关键路径计算结果 =====" << endl;
    cout << "工程最短总工期:" << ve[endNode] << endl;
    cout << "关键节点:";
    for (int i = 1; i <= n; i++) {
        if (ve[i] == vl[i]) {
            cout << i << " ";
        }
    }
    cout << endl;

    cout << "关键活动(边):" << endl;
    for (int u = 1; u <= n; u++) {
        // 筛选关键节点之间的边
        if (ve[u] != vl[u]) continue;
        for (Edge e : adj[u]) {
            int v = e.to, w = e.w;
            if (ve[v] == vl[v] && ve[v] == ve[u] + w) {
                cout << "节点" << u << " -> 节点" << v << " (工期:" << w << ")" << endl;
            }
        }
    }
}

int main() {
    // 初始化
    memset(inDegree, 0, sizeof(inDegree));
    int n, m;
    cout << "请输入节点数、边数:";
    cin >> n >> m;

    // 构建正向、逆向邻接表
    for (int i = 0; i < m; i++) {
        int u, v, w;
        cout << "请输入第" << i + 1 << "条边(起点 终点 权重):";
        cin >> u >> v >> w;
        adj[u].emplace_back(v, w);
        reverseAdj[v].emplace_back(u, w);
        inDegree[v]++;
    }

    // 拓扑排序判环
    if (!topoSort(n)) {
        cout << "图中存在环路,无关键路径!" << endl;
        return 0;
    }

    // 计算并输出关键路径
    criticalPath(n);
    return 0;
}
相关推荐
维克兜率天43 分钟前
【维克】动量指标家族:RSI、ROC、CCI、Momentum全面解析
python·算法
AI情绪识别开源2 小时前
检信 AI 智能推广平台(代号:JX-Promote)
人工智能·算法·erlang
老当益壮梁奶奶2 小时前
Linux软件编程学习笔记(八):进程间通信详解(1)
linux·c语言·笔记·学习·算法
不会就选b2 小时前
算法日常・每日刷题--<BFS拓扑排序>4
算法
不正经学生3 小时前
C语言动态内存管理(上):堆上的自由与责任
c语言·开发语言·c++·算法·面试
伟大的车尔尼3 小时前
贪心的概念
数据结构·算法·贪心
方方洛3 小时前
vllm教程-00-前言与导读
人工智能·算法·vllm
AI情绪识别开源3 小时前
检信AI高一分班分科智选评估系统 v2.0测试报告
开发语言·数据结构·人工智能·科技
IT毕设实战小研3 小时前
电影数据可视化推荐系统
大数据·后端·爬虫·python·算法·信息可视化·课程设计
且随疾风前行.3 小时前
从驱动来分析服务的添加过程
算法