有向无环图(DAG)中的最长路径问题
字数 1369 2025-11-03 12:22:39

有向无环图(DAG)中的最长路径问题

题目描述
给定一个有向无环图(DAG),每个边有一个权重(可能为正、负或零),要求找到从任意源点到任意终点的最长路径(即路径上所有边权重之和最大的路径)。若图中存在多个连通分量,需考虑所有可能的起点和终点。注意:DAG中无环,因此不存在正权环导致路径无限长的问题,但负权边是允许的。

解题过程

  1. 问题分析

    • DAG的特性允许我们使用拓扑排序来线性化顶点顺序,确保处理顶点时其所有前驱顶点已被处理。
    • 最长路径问题可通过动态规划(DP)解决:设dist[v]表示从某个起点到顶点v的最长路径长度。初始时,所有dist[v]设为负无穷(表示不可达),起点的dist设为0(若以固定起点计算)。
    • 对于每个顶点v,遍历其所有入边或出边(取决于DP方向)。若以拓扑顺序处理顶点,从起点开始沿边更新后继顶点的距离,可保证无后效性。
  2. 算法步骤

    • 步骤1:拓扑排序
      使用Kahn算法或DFS对DAG进行拓扑排序,得到顶点序列topo_order

      • Kahn算法:统计每个顶点的入度,将入度为0的顶点加入队列,依次处理并更新邻接顶点的入度。
      • 示例:对于顶点序列A→B→C,拓扑排序结果为[A, B, C]
    • 步骤2:初始化距离数组
      若求全局最长路径(任意起点),初始化dist数组为负无穷(-inf)。若指定起点s,则设dist[s] = 0,其他为-inf

      • 理由:负无穷确保只有实际可达的路径才会被更新。
    • 步骤3:动态规划转移
      按拓扑顺序遍历每个顶点u

      • dist[u]-inf,说明u不可达,跳过。
      • 遍历u的所有出边(u, v, w)w为边权重):
        • 更新dist[v] = max(dist[v], dist[u] + w)
      • 关键点:由于按拓扑顺序处理,当处理到u时,所有指向u的路径已计算完毕,因此udist值已确定。
    • 步骤4:获取结果
      若求从起点s到终点t的路径,直接返回dist[t]。若求全局最长路径,遍历所有顶点的dist值取最大值。

  3. 示例演示
    考虑DAG如下(边权重括号内):

    A --(2)→ B --(1)→ D
     \       |        ^
      \-(4)→ C --(3)-/
    
    • 拓扑排序:[A, B, C, D]
    • 初始化dist = [-inf, -inf, -inf, -inf],设起点为A,则dist[A] = 0
    • 处理A:更新B(dist[B]=max(-inf,0+2)=2),更新C(dist[C]=max(-inf,0+4)=4)。
    • 处理B:更新D(dist[D]=max(-inf,2+1)=3)。
    • 处理C:更新D(dist[D]=max(3,4+3)=7)。
    • 处理D:无出边。
    • 结果:从A到D的最长路径为A→C→D,长度为7。
  4. 复杂度分析

    • 拓扑排序时间复杂度为O(V+E)。
    • DP过程遍历所有边一次,复杂度O(V+E)。
    • 总复杂度为O(V+E),优于一般图(含环)最长路径的NP难问题。
  5. 边界情况

    • 若图中无路径(如不连通且起点无法到终点),返回负无穷。
    • 所有边权重为负时,最长路径可能为0(起点自身)。

总结
通过拓扑排序结合动态规划,可高效解决DAG最长路径问题,核心是利用DAG的无环特性确保DP顺序的正确性。

有向无环图(DAG)中的最长路径问题 题目描述 给定一个有向无环图(DAG),每个边有一个权重(可能为正、负或零),要求找到从任意源点到任意终点的最长路径(即路径上所有边权重之和最大的路径)。若图中存在多个连通分量,需考虑所有可能的起点和终点。注意:DAG中无环,因此不存在正权环导致路径无限长的问题,但负权边是允许的。 解题过程 问题分析 DAG的特性允许我们使用拓扑排序来线性化顶点顺序,确保处理顶点时其所有前驱顶点已被处理。 最长路径问题可通过动态规划(DP)解决:设 dist[v] 表示从某个起点到顶点 v 的最长路径长度。初始时,所有 dist[v] 设为负无穷(表示不可达),起点的 dist 设为0(若以固定起点计算)。 对于每个顶点 v ,遍历其所有入边或出边(取决于DP方向)。若以拓扑顺序处理顶点,从起点开始沿边更新后继顶点的距离,可保证无后效性。 算法步骤 步骤1:拓扑排序 使用Kahn算法或DFS对DAG进行拓扑排序,得到顶点序列 topo_order 。 Kahn算法:统计每个顶点的入度,将入度为0的顶点加入队列,依次处理并更新邻接顶点的入度。 示例:对于顶点序列 A→B→C ,拓扑排序结果为 [A, B, C] 。 步骤2:初始化距离数组 若求全局最长路径(任意起点),初始化 dist 数组为负无穷( -inf )。若指定起点 s ,则设 dist[s] = 0 ,其他为 -inf 。 理由:负无穷确保只有实际可达的路径才会被更新。 步骤3:动态规划转移 按拓扑顺序遍历每个顶点 u : 若 dist[u] 为 -inf ,说明 u 不可达,跳过。 遍历 u 的所有出边 (u, v, w) ( w 为边权重): 更新 dist[v] = max(dist[v], dist[u] + w) 。 关键点 :由于按拓扑顺序处理,当处理到 u 时,所有指向 u 的路径已计算完毕,因此 u 的 dist 值已确定。 步骤4:获取结果 若求从起点 s 到终点 t 的路径,直接返回 dist[t] 。若求全局最长路径,遍历所有顶点的 dist 值取最大值。 示例演示 考虑DAG如下(边权重括号内): 拓扑排序: [A, B, C, D] 。 初始化 dist = [-inf, -inf, -inf, -inf] ,设起点为A,则 dist[A] = 0 。 处理A:更新B( dist[B]=max(-inf,0+2)=2 ),更新C( dist[C]=max(-inf,0+4)=4 )。 处理B:更新D( dist[D]=max(-inf,2+1)=3 )。 处理C:更新D( dist[D]=max(3,4+3)=7 )。 处理D:无出边。 结果:从A到D的最长路径为A→C→D,长度为7。 复杂度分析 拓扑排序时间复杂度为O(V+E)。 DP过程遍历所有边一次,复杂度O(V+E)。 总复杂度为O(V+E),优于一般图(含环)最长路径的NP难问题。 边界情况 若图中无路径(如不连通且起点无法到终点),返回负无穷。 所有边权重为负时,最长路径可能为0(起点自身)。 总结 通过拓扑排序结合动态规划,可高效解决DAG最长路径问题,核心是利用DAG的无环特性确保DP顺序的正确性。