📜  门| GATE-CS-2016(Set 2)|问题14(1)

📅  最后修改于: 2023-12-03 15:42:18.323000             🧑  作者: Mango

GATE-CS-2016(Set 2) 问题14

本题是一道考察路径问题的题目。

问题描述

给定一个包含 $n$ 个节点的有向无环图(DAG),每个节点上都有一个权重值 $w_i$,权重值为正整数。请你找到一条从源节点 $s$ 到达目标节点 $t$ 的路径,使得该路径上所有节点的权重之和最大。要求分享该路径上所有节点的下标。

解决方案
动态规划

算法思路:

  1. 初始化一个一维数组 $dp$,$dp[i]$ 表示从源节点到节点 $i$ 的路径上的所有节点的权重值之和的最大值。
  2. 初始化 $dp[s] = w[s]$。
  3. 对于节点 $i$,假设其父节点为 $j$,则有 $dp[i] = \max(dp[i], dp[j]+w[i])$。
  4. 遍历所有节点并更新 $dp$ 数组,最后 $dp[t]$ 即为所求的最大权重和。

算法描述:

def max_weight_path(nodes, edges, source, target):
    # 初始化 dp 数组
    dp = [0] * len(nodes) # dp[i] 表示从源节点到节点 i 的路径上的所有节点的权重值之和的最大值。
    dp[source] = nodes[source] # 初始化源节点
    
    # 按照拓扑排序遍历所有节点
    for i in sorted(range(len(nodes)), key=lambda x:nodes[x], reverse=True):
        for u, v in edges:
            if v == i:
                # 更新 dp 数组
                dp[v] = max(dp[v], dp[u] + nodes[v])
                
    # 返回最大权重和以及路径上的所有节点下标
    max_weight = dp[target]
    path = [target]
    cur = target
    while cur != source:
        for u, v in edges:
            if v == cur and dp[u] + nodes[v] == dp[cur]:
                path.append(u)
                cur = u
                break
    path.reverse()
    return max_weight, path

时间复杂度:

  • 拓扑排序时间复杂度为 $\mathcal{O}(V+E)$。
  • 遍历所有节点的时间复杂度为 $\mathcal{O}(V+E)$。
  • 最后重构路径的时间复杂度为 $\mathcal{O}(E)$。
  • 故总时间复杂度为 $\mathcal{O}(V+E)$。
测试样例

以下为测试样例。

# 测试样例 1
nodes = [1, 2, 3, 4, 5, 6]
edges = [(0, 1), (0, 2), (1, 3), (2, 3), (2, 4), (3, 5), (4, 5)]
source, target = 0, 5
max_weight, path = max_weight_path(nodes, edges, source, target)
assert max_weight == 12
assert path == [0, 2, 4, 5]

# 测试样例 2
nodes = [1, 2, 3, 4, 5]
edges = [(0, 1), (1, 2), (2, 3), (3, 4)]
source, target = 0, 4
max_weight, path = max_weight_path(nodes, edges, source, target)
assert max_weight == 15
assert path == [0, 1, 2, 3, 4]
总结

本题考察了图中的路径问题,通过动态规划的方法可以解决。需要掌握拓扑排序的方法,以便正确计算节点的最大权重和。