📜  门| GATE-CS-2005 |第 76 题(1)

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

门| GATE-CS-2005 |第 76 题

题目描述

给定一个 N 个节点的树,每个节点有一个权重值。定义树的重心为树上某个节点,如果将该节点删除后,最大的连通块不超过 N/2,我们称该节点为树的重心。在给定的树中找到树的所有重心。

输入格式

第一行输入一个整数 $N$,表示树的节点数。

接下来 $N$ 行,每行输入两个整数 $u$ 和 $w$,表示节点的编号和权重值。

接下来 $N-1$ 行,每行输入两个整数 $u$ 和 $v$,表示树上的一条边。

输出格式

输出一个或多个整数,表示树的重心的编号,按编号升序排列。

示例

输入:

5
1 1
2 1
3 1
4 1
5 1
1 2
2 3
2 4
1 5

输出:

2
题解

题目要求找到树的重心,而重心有一个重要的性质:树的重心是树上最深的叶子节点的父节点。

因此,我们可以使用 DFS 计算每个节点的子树大小和最深叶子节点的深度。然后,我们可以使用 BFS 或 DFS 来查询树的重心,并将它们按升序排列输出。

以下是 Python 的实现:

from collections import deque
from typing import List, Tuple

def find_centroids(n: int, nodes: List[Tuple[int, int]], edges: List[Tuple[int, int]]) -> List[int]:
    # Step 1: Build adjacency list to represent the tree
    adj_list = [[] for _ in range(n)]
    for u, v in edges:
        adj_list[u-1].append(v-1)
        adj_list[v-1].append(u-1)

    # Step 2: Compute each node's subtree size and maximum depth
    size, depth = [0] * n, [0] * n

    def dfs(node, parent):
        size[node] = 1
        for child in adj_list[node]:
            if child != parent:
                dfs(child, node)
                size[node] += size[child]
                depth[node] = max(depth[node], depth[child]+1)

    dfs(0, -1)

    # Step 3: Find all centroids
    q = deque([0])

    while q:
        node = q.popleft()
        is_centroid = True

        for child in adj_list[node]:
            if size[child] > n // 2:
                is_centroid = False
                break

        if is_centroid or node == 0:
            yield node + 1

        for child in adj_list[node]:
            q.append(child)
时间复杂度

这个算法的时间复杂度为 $O(N)$,其中 $N$ 是树的节点数。这是因为我们只需要遍历一遍树来计算每个节点的子树大小和深度,以及一遍 BFS 或 DFS 来查找树的重心。