📅  最后修改于: 2023-12-03 15:23:03.562000             🧑  作者: Mango
一个由n个节点组成的树,其中每个节点都有一个权值。现在请你找出权值最大的子树,输出该子树的根节点编号以及该子树的权值之和。
输入的第一行包含一个整数n,表示树的节点个数。(1≤n≤10^5)
接下来的n行,其中第i行包含一个整数w_i,表示第i个节点的权值。(1≤w_i≤10^3)
接下来的n−1行,每行包含两个整数u,v,表示u和v之间有一条边,即u和v分别是这条边所连的两个节点。
输出一行,包含两个整数,第一个整数表示子树的根节点编号,第二个整数表示该子树的权值之和。
输入:
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)