📅  最后修改于: 2023-12-03 14:58:27.436000             🧑  作者: Mango
给定一个有向无环图,每个节点都有一个权重值。现在,我们要找到一条路径使得路径的总权值最大化,并且这条路径上所有的节点都满足以下条件:
输出这条路径的最大权值和。
例如,在下面这个图中,从节点1到节点5的路径上的所有节点都满足条件1和条件2,路径的最大权值和是24。
本题是一道典型的动态规划问题。我们按照拓扑排序的顺序遍历有向无环图中的每个节点,对于每个节点,我们记录到达该节点的最大权值,即该节点的权值加上前驱节点的最大权值。具体而言,设$w_i$表示节点$i$的权值,$last_j$表示节点$j$的前驱节点,$dp_i$表示到达节点$i$的最大权值,则有:
$$dp_i = w_i + dp_{last_i}$$
对于入度为0的节点(即没有前驱节点的节点),将其最大权值设为其权值本身。对于出度为0的节点(即没有后继节点的节点),将其最大权值设为0。最终,在所有到达终止节点的路径中,找到最大的路径权值,即为所求的答案。
时间复杂度为$O(n)$,其中$n$为节点数目。
def max_weight_path(graph):
n = len(graph) # 图中节点数
dp = [0] * n # 记录到达每个节点的最大权值
# 拓扑排序
node_order = []
in_degree = [0] * n # 记录所有节点的入度
for i in range(n):
for v in graph[i]:
in_degree[v] += 1
queue = [i for i in range(n) if in_degree[i] == 0]
while queue:
node = queue.pop(0)
node_order.append(node)
for v in graph[node]:
in_degree[v] -= 1
if in_degree[v] == 0:
queue.append(v)
# 按拓扑序遍历每个节点,更新最大权值
for node in node_order:
max_weight = 0
for last_node in graph[node]:
max_weight = max(max_weight, dp[last_node])
dp[node] = max_weight + (w[node] if in_degree[node] != 0 else 0)
# 找到所有到达终止节点的路径中的最大权值
max_path_weight = max([dp[i] for i in range(n) if len(graph[i]) == 0])
return max_path_weight
注:以上代码中,graph
为输入的图,是一个邻接表表示。其中w[i]
表示节点$i$的权值,为全局变量。