📅  最后修改于: 2023-12-03 14:58:20.897000             🧑  作者: Mango
门| GATE CS 2020 |第 48 题是一道计算机科学的算法题,涉及到了关键路径问题和拓扑排序的知识。
给定一个 DAG (有向无环图) 和每个顶点的权重,找到一条从源顶点到汇顶点的路径,使得该路径上所有顶点的权重之和最大。同时,输出路径上经过的所有顶点。
输入以邻接表的形式给出一个 DAG。第一行输入两个正整数 N 和 M,表示顶点数和边数。接下来 M 行,每行描述一个边,包含两个正整数 u 和 v,表示一条从顶点 u 到顶点 v 的有向边。接下来一行输入 N 个正整数,表示每个顶点的权重。
输出路径上所有顶点和它们的权重之和。
该问题可以通过拓扑排序和动态规划求解。首先,通过拓扑排序将图转化为 DAG,找到入度为 0 的顶点作为源顶点,并将其权重初始化为 dp 值。接着,对每个后继顶点,计算该顶点的 dp 值并更新其前驱顶点。最后,从汇顶点回溯到源顶点,输出路径上的所有顶点和它们的权重。
以下是 Python 语言的代码示例,实现了题目要求的算法。
from collections import deque
n, m = map(int, input().split())
g = [[] for _ in range(n)]
din = [0] * n
w = list(map(int, input().split()))
vis = [False] * n
dp = [-1] * n
path = [-1] * n
q = deque()
for i in range(m):
u, v = map(int, input().split())
g[u].append(v)
din[v] += 1
for i in range(n):
if din[i] == 0:
dp[i] = w[i]
path[i] = i
q.append(i)
while len(q) > 0:
u = q.popleft()
if vis[u]:
continue
vis[u] = True
for v in g[u]:
din[v] -= 1
if din[v] == 0:
q.append(v)
if dp[v] < dp[u] + w[v]:
dp[v] = dp[u] + w[v]
path[v] = u
ans = []
u = n - 1
while u != path[u]:
ans.append((u, w[u]))
u = path[u]
ans.append((u, w[u]))
ans.reverse()
for i in range(len(ans)):
print(ans[i][0], ans[i][1])
该代码首先读入输入,然后初始化拓扑排序和动态规划需要用到的数据结构。接着,将 DAG 转换为拓扑排序,并计算每个顶点的 dp 值。最后回溯到源顶点,输出路径上的所有顶点和它们的权重。
通过本题,我们学习了如何通过拓扑排序和动态规划解决关键路径问题,同时对问题求解的步骤和细节有了更深刻的认识。