蓝桥省赛 生命之树 深搜 树形DP
🍑 算法题解专栏
🍑 生命之树
输入
5
1 -2 -3 4 5
4 2
3 1
1 2
2 5
输出
8
🍑
import java.util.Arrays;
import java.util.Scanner;
public class 生命之树
{
static int N = (int) 1e5 + 10;
static int M = 2 * N, idx;
static int[] w = new int[N];
static int[] h = new int[N];
static int[] ne = new int[M];
static int[] e = new int[M];
static long[] f = new long[N];//在以u为根的子树中包含u的所有连通块的权值的最大值
public static void main(String[] args)
{
Arrays.fill(h, -1);// 头指针数组初始化
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
for (int i = 1; i <= n; i++)
w[i] = sc.nextInt();
for (int i = 0; i < n - 1; i++)
{
int a = sc.nextInt();
int b = sc.nextInt();
add(a, b);
add(b, a);
}
dfs(1, -1);
long res = f[1];
for (int i = 2; i <= n; i++)
res = Math.max(res, f[i]);
if (res < 0)// 答案小于 0 时 不如不选
res = 0;
System.out.println(res);
}
// u 表示当前节点,p 表示父节点
private static void dfs(int u, int p)
{
f[u] = w[u];
for (int i = h[u]; i != -1; i = ne[i])
{
int t = e[i];
if (t != p)// 避免走回头路(无向图)
{
dfs(t, u);// 递归搜索子树
f[u] += Math.max(0, f[t]);
}
}
}
// 添加一条 a 指向 b 的有向边
private static void add(int a, int b)
{
e[idx] = b;
ne[idx] = h[a];
h[a] = idx++;
}
}