📌  相关文章
📜  国际空间研究组织 | ISRO CS 2014 |问题 21(1)

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

ISRO CS 2014 | 问题 21

题目描述

一个由n个节点组成的树,其中每个节点都有一个权值。现在请你找出权值最大的子树,输出该子树的根节点编号以及该子树的权值之和。

输入

输入的第一行包含一个整数n,表示树的节点个数。(1≤n≤10^5)

接下来的n行,其中第i行包含一个整数w_i,表示第i个节点的权值。(1≤w_i≤10^3)

接下来的n−1行,每行包含两个整数u,v,表示u和v之间有一条边,即u和v分别是这条边所连的两个节点。

输出

输出一行,包含两个整数,第一个整数表示子树的根节点编号,第二个整数表示该子树的权值之和。

Example

输入:

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

输出:

3 12
问题分析

这是一道求树的子树中权值最大的题目。

我们可以考虑使用深度优先遍历来解决这一问题。

我们可以从根节点开始进行深度优先遍历,将权值相加,并记录当前权值最大的子树。

我们可以使用一个递归函数来实现深度优先遍历,其中参数表示当前节点的编号和当前子树的总权值。

在遍历到每个节点的时候,我们可以比较当前子树的权值与记录的权值最大的子树的权值,并更新相应的信息。

最终,我们可以返回记录的权值最大的子树的根节点编号和总权值。

代码实现
def dfs(u, s, vis, sub, G):
    """
    u: 当前节点编号
    s: 当前子树权值和
    vis: 节点是否已被访问的标记
    sub: 记录子树信息的数组
    G: 存储树的邻接表
    """
    vis[u] = True  # 标记节点已被访问
    size = 1  # 当前子树的大小
    for v in G[u]:
        if not vis[v]:
            size += dfs(v, s, vis, sub, G)
    sub[u] = size  # 记录子树大小
    return s + w[u]  # 返回当前子树的权值和
        

n = int(input())
w = [0] + [int(input()) for i in range(n)]  # 节点权值
G = [[] for i in range(n+1)]  # 存储邻接表
for i in range(n-1):
    u, v = map(int, input().split())
    G[u].append(v)
    G[v].append(u)

vis = [False] * (n+1)  # 标记节点是否已被访问
sub = [0] * (n+1)  # 记录子树大小
max_sub = -float('inf')  # 最大子树权值和
max_node = 0  # 最大子树的根节点编号

for i in range(1, n+1):
    if not vis[i]:
        s = dfs(i, 0, vis, sub, G)
        for j in range(1, n+1):
            if sub[j] > max_sub:
                max_sub = sub[j]
                max_node = j

print(max_node, s)

代码片段返回markdown

```python
def dfs(u, s, vis, sub, G):
    """
    u: 当前节点编号
    s: 当前子树权值和
    vis: 节点是否已被访问的标记
    sub: 记录子树信息的数组
    G: 存储树的邻接表
    """
    vis[u] = True  # 标记节点已被访问
    size = 1  # 当前子树的大小
    for v in G[u]:
        if not vis[v]:
            size += dfs(v, s, vis, sub, G)
    sub[u] = size  # 记录子树大小
    return s + w[u]  # 返回当前子树的权值和
        

n = int(input())
w = [0] + [int(input()) for i in range(n)]  # 节点权值
G = [[] for i in range(n+1)]  # 存储邻接表
for i in range(n-1):
    u, v = map(int, input().split())
    G[u].append(v)
    G[v].append(u)

vis = [False] * (n+1)  # 标记节点是否已被访问
sub = [0] * (n+1)  # 记录子树大小
max_sub = -float('inf')  # 最大子树权值和
max_node = 0  # 最大子树的根节点编号

for i in range(1, n+1):
    if not vis[i]:
        s = dfs(i, 0, vis, sub, G)
        for j in range(1, n+1):
            if sub[j] > max_sub:
                max_sub = sub[j]
                max_node = j

print(max_node, s)