拓扑排序与关键路径是图论中用于有向无环图(DAG)和AOE网(Activity On Edge Network)的重要算法

拓扑排序与关键路径是图论中用于有向无环图(DAG)和AOE网(Activity On Edge Network)的重要算法,常用于项目调度与工期优化分析。

  • AOE网:是一种带权有向无环图,其中:

    • 顶点表示事件(Event),即状态或里程碑;
    • 有向边表示活动(Activity),边上的权值表示该活动所需持续时间;
    • 源点(入度为0)表示工程开始,汇点(出度为0)表示工程结束。
  • 拓扑排序:用于检测AOE网是否有环(若无法拓扑排序,则存在环,不能进行关键路径分析),并为后续计算提供顶点处理顺序(按事件发生的逻辑先后)。

  • 最早开始时间(ve):从源点出发,沿所有路径到达某事件的最长路径长度(即该事件最早可能发生的时刻)。通过正向拓扑序动态规划计算:
    ve[j] = max{ ve[i] + weight(i→j) },对所有前驱i。

  • 最晚开始时间(vl):在保证工程总工期不变的前提下,该事件最迟必须发生的时刻。通过逆向拓扑序(从汇点反推)计算:
    vl[i] = min{ vl[j] − weight(i→j) },对所有后继j。

  • 关键路径:由所有满足 ve[i] == vl[i] 的事件(顶点)所构成的、从源点到汇点的路径;其上所有活动(边)的最早开始时间 = 最晚开始时间(即 e = l),这些活动称为关键活动,无机动时间,延迟将导致整个工期延长。

“32次”可能指某次练习/考试中该知识点共出现32题,或某算法执行中涉及32次关键操作(如32条边参与松弛/更新),需结合上下文确认;但核心仍围绕AOE建模、拓扑排序验证、ve/vl双遍历及关键路径提取。

# 简化版AOE关键路径计算示意(需先完成拓扑排序)
def critical_path(graph, n, source, sink):
    # graph: 邻接表,graph[u] = [(v, w), ...]
    ve = [-float('inf')] * n; ve[source] = 0
    vl = [float('inf')] * n; vl[sink] = ve[sink]  # 总工期 = ve[sink]
    
    # 正向拓扑序更新ve(需提前获得拓扑序列topo_order)
    for u in topo_order:
        for v, w in graph[u]:
            if ve[v] < ve[u] + w:
                ve[v] = ve[u] + w
    
    # 逆向拓扑序更新vl
    for u in reversed(topo_order):
        for v, w in graph[u]:
            if vl[u] > vl[v] - w:
                vl[u] = vl[v] - w
    
    # 找关键活动:边u→v满足 ve[u] == vl[u] and ve[v] == vl[v] and ve[u] + w == ve[v]
    critical_edges = []
    for u in range(n):
        for v, w in graph[u]:
            if ve[u] == vl[u] and ve[v] == vl[v] and ve[u] + w == ve[v]:
                critical_edges.append((u, v, w))
    return critical_edges

判断一个AOE网中是否存在多条关键路径,核心在于:从源点到汇点是否存在两条或以上互不重合(或部分重合但整体不同)的最长路径(即总权值等于工程最短完成时间的路径)。关键路径本质是AOE网中源点到汇点的最长路径(因工期由最长路径决定),因此多条关键路径 ⇔ 存在多条长度均等于最大路径长度(即 ve[汇点])的不同有向路径

✅ 判断方法:

  1. 先求出总工期 T = ve[汇点](即源点到汇点的最长路径长度);
  2. 从源点出发,用DFS/BFS或动态规划统计:从源点到汇点、路径长度恰好为 T 的不同路径条数
    • 可定义 dp[v] 表示从源点到顶点 v 的长度为 ve[v] 的路径条数;
    • 初始化 dp[source] = 1
    • 按拓扑序遍历,对每条边 u → v 权值 w,若 ve[u] + w == ve[v],则 dp[v] += dp[u]
  3. dp[sink] ≥ 2,则存在多条关键路径。

⚠️ 注意:路径“不同”指顶点序列不同(即使共享部分边,只要整体路径不完全一致,即算多条)。

📌 举例说明(简洁AOE网):

事件:A(源点)、B、C、D(汇点)  
活动(边)及权值:  
A→B : 2  
A→C : 3  
B→D : 4  
C→D : 3  

计算:

  • ve[A]=0, ve[B]=2, ve[C]=3, ve[D]=max(2+4, 3+3)=max(6,6)=6 → 总工期=6
  • 检查路径:
    A→B→D:长度=2+4=6
    A→C→D:长度=3+3=6
    → 两条路径长度均为6,且顶点序列不同(ABD vs ACD)⇒ 存在两条关键路径

此时 dp[A]=1,
dp[B] += dp[A] =1(因 ve[A]+2ve[B]),
dp[C] += dp[A] =1(因 ve[A]+3
ve[C]),
dp[D] += dp[B] + dp[C] =1+1=2dp[D]=2,确认多条关键路径。

进一步观察:B和C均满足 ve[x]==vl[x](可验证 vl[D]=6, vl[B]=6−4=2, vl[C]=6−3=3, vl[A]=min(2,3)=0),故A、B、C、D均为关键事件;但关键活动是 A→B、B→D、A→C、C→D 全部四条——说明整个网络呈“并行双路径”结构,无冗余边。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Bol5261

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值