有向无环图(DAG)中的最长路径问题
字数 1369 2025-11-03 12:22:39
有向无环图(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 --(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。
- 拓扑排序:
-
复杂度分析
- 拓扑排序时间复杂度为O(V+E)。
- DP过程遍历所有边一次,复杂度O(V+E)。
- 总复杂度为O(V+E),优于一般图(含环)最长路径的NP难问题。
-
边界情况
- 若图中无路径(如不连通且起点无法到终点),返回负无穷。
- 所有边权重为负时,最长路径可能为0(起点自身)。
总结
通过拓扑排序结合动态规划,可高效解决DAG最长路径问题,核心是利用DAG的无环特性确保DP顺序的正确性。