📜  门| GATE CS 2020 |第 48 题(1)

📅  最后修改于: 2023-12-03 14:58:20.897000             🧑  作者: Mango

门| GATE CS 2020 |第 48 题介绍

门| 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 值。最后回溯到源顶点,输出路径上的所有顶点和它们的权重。

总结

通过本题,我们学习了如何通过拓扑排序和动态规划解决关键路径问题,同时对问题求解的步骤和细节有了更深刻的认识。