📜  门| GATE 2017 MOCK II |问题6(1)

📅  最后修改于: 2023-12-03 14:58:18.045000             🧑  作者: Mango

GATE 2017 MOCK II - 问题6

该问题是关于树的遍历和深度优先搜索(DFS)的。

问题描述

给定一棵有 $n$ 个节点的有根树,每个节点的编号从 $1$ 到 $n$(根节点为 $1$)。每个节点有一个权值 $a_i$,可以为正数、负数或零。请计算以下两个值:

  1. 以节点 $1$ 为根节点进行 DFS 遍历时,遍历到权值之和最大的路径的权值和。
  2. 以任意一个节点为根节点进行 DFS 遍历时,遍历到权值之和最大的路径的权值和。
输入格式

第一行包含一个整数 $n$。

第二行包含 $n$ 个整数 $a_1,a_2,\ldots,a_n$,表示每个节点的权值。

接下来 $n-1$ 行,每行包含两个整数 $u,v$,表示一条从节点 $u$ 到节点 $v$ 的边。

输出格式

一行两个整数,表示第一个和第二个问题的答案,用空格隔开。

示例

输入:

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

输出:

8 10
思路

对于第一个问题,可以从根节点开始 DFS 遍历,对于每个节点,维护两个变量:$maxsum$ 表示以该节点为终点的最大路径和,$ans$ 表示全局最大路径和。对于当前节点,遍历其所有子节点,并更新 $maxsum$。那么,$ans$ 可以由以下三种情况得到:

  • 以当前节点为终点的路径最大。
  • 以当前节点为起点、子树中的路径最大。
  • 以当前节点为分界点、左右子树路径最大。

对于第二个问题,可以以任意一个节点为起点进行 DFS 遍历,在遍历的过程中维护 $maxsum$ 和 $ans$。遍历到一个节点时,先更新 $maxsum$,再更新 $ans$。$ans$ 的取值同第一个问题。

代码
def dfs1(u, fa):
    maxsum = 0
    for v in g[u]:
        if v == fa:
            continue
        dfs1(v, u)
        maxsum = max(maxsum, 0) + a[v]
        ans[0] = max(ans[0], maxsum)
    ans[0] = max(ans[0], maxsum + a[u])

def dfs2(u, fa):
    maxsum = a[u]
    for v in g[u]:
        if v == fa:
            continue
        maxsum = max(maxsum, 0) + a[v]
        ans[1] = max(ans[1], maxsum)
        dfs2(v, u)

n = int(input())
a = [int(x) for x in input().split()]
g = [[] for i in range(n+1)]
for i in range(n-1):
    u, v = [int(x) for x in input().split()]
    g[u].append(v)
    g[v].append(u)

ans = [a[1]]*2
dfs1(1, 0)
dfs2(1, 0)
print(ans[0], ans[1])

代码片段按markdown标注: