📜  门| GATE CS 2021 |设置 1 |第 30 题(1)

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

门 | GATE CS 2021 | 设置 1 | 第 30 题

本题是2021年GATE计算机科学考试中的第30题,涉及到有向无环图中的关键路径问题。

题目描述

给定一个由n个顶点和m条边组成的有向无环图。每个边连接两个顶点,并具有关联的权重值。请找到这个图的关键路径,即连接源节点和终节点的最长路径。假定没有两个顶点之间有多个边。

输入格式

输入的第一行包含两个整数n和m,表示图的节点数和边数。接下来的m行描述图的每条边。每行包含三个整数u,v和w,表示从节点u到节点v的有向边,其权重值为w。

输出格式

输出一个整数,表示图的关键路径的长度。

示例输入输出

输入:

5 7
0 1 5
0 2 3
1 3 6
1 2 2
2 3 7
2 4 4
3 4 2

输出:

15
解题思路

首先需要确定有向无环图中的每个节点的最早开始时间和最迟开始时间。同时,需要确定每个节点之间的权重值。

使用拓扑排序的方法可以实现这个问题。首先,将所有入度为0的节点入队。然后,从队列中取出节点并将其所有出度节点的入度减1。如果一个节点的入度为0,则将其加入队列。重复此过程,直到队列为空。

在此过程中,可以维护每个节点的最早开始时间。对于每个节点,其最早开始时间等于前驱节点中最晚的完成时间加上边的权重。当遍历完所有节点后,最后一个节点的最早开始时间就是整个图的最长路径。同时,还可以求出每个节点的最迟开始时间,以及相邻节点之间的权重。

代码实现
from collections import deque

n, m = map(int, input().split())
graph = [[] for _ in range(n)]
in_degree = [0] * n
out_degree = [0] * n
earliest = [0] * n
latest = [float('inf')] * n

for _ in range(m):
    u, v, w = map(int, input().split())
    graph[u].append((v, w))
    in_degree[v] += 1
    out_degree[u] += 1

# 拓扑排序
queue = deque([i for i in range(n) if in_degree[i] == 0])
while queue:
    u = queue.popleft()
    for v, w in graph[u]:
        in_degree[v] -= 1
        if in_degree[v] == 0:
            queue.append(v)
        earliest[v] = max(earliest[v], earliest[u] + w)

# 计算最长路径
latest[n - 1] = earliest[n - 1]
for u in range(n - 2, -1, -1):
    for v, w in graph[u]:
        latest[u] = min(latest[u], latest[v] - w)
for u in range(n):
    for v, w in graph[u]:
        slack = latest[v] - earliest[u] - w
        if slack == 0:
            print(earliest[n - 1])
            exit()

assert False, "no feasible solution"
参考资料