📜  门| GATE-CS-2017(套装1)|问题 18(1)

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

问题 18

本问题要求编写程序,利用 贪心算法 在一个有向无环图中确定每个节点的最长路径的长度。

程序接口说明
def longest_path(n: int, edges: List[Tuple[int, int]]) -> List[int]:
    pass
  • n: 图中节点的数量,一个正整数。
  • edges: 表示有向图的所有边。每个元素是 $(u, v)$,表示从节点 $u$ 向节点 $v$ 连一条边。保证每对 $u, v$ 最多出现一次。
  • 返回最长路径长度。
使用样例
n = 4
edges = [(0, 1), (0, 2), (1, 2), (2, 3)]
print(longest_path(n, edges))

输出

3
思路与方法
  • 用一个列表 $L$ 记录每个节点的当前最长路径长度。初始化为 0。
  • 从图中任意选择一个未被处理过的节点 $u$。将节点 $u$ 的当前最长路径长度设为 $max { L(v) + 1 }$,其中 $L(v)$ 表示从节点 $v$ 出发的路径长度的最大值,$(v, u)$ 是一条从 $v$ 到 $u$ 的有向边。
  • 重复上述步骤,直到所有节点都被处理过。
算法实现
from typing import List, Tuple

def longest_path(n: int, edges: List[Tuple[int, int]]) -> List[int]:
    graph = [[] for _ in range(n)]
    in_degree = [0] * n    # 计算每个节点的入度,in_degree[i] 表示节点 i 的入度
    for u, v in edges:
        graph[u].append(v)
        in_degree[v] += 1
    queue = []    # 保存入度为 0 的节点
    for i in range(n):
        if in_degree[i] == 0:
            queue.append(i)
    longest_paths = [0] * n    # 保存每个节点的最长路径长度,初始化为 0
    while queue:
        u = queue.pop(0)
        for v in graph[u]:
            in_degree[v] -= 1
            longest_paths[v] = max(longest_paths[v], longest_paths[u] + 1)
            if in_degree[v] == 0:
                queue.append(v)
    return max(longest_paths)
复杂度分析
  • 时间复杂度:$O(V+E)$,其中 $V$ 是节点数,$E$ 是边数。由于每个节点最多被遍历一次,每条边最多被遍历一次,因此时间复杂度为 $O(V+E)$。
  • 空间复杂度:$O(V)$。需要一个数组 $L$ 存储每个节点的最长路径长度,和一个队列保存入度为 0 的节点。所有数组的长度都为 $V$,因此空间复杂度为 $O(V)$。