Loading

AcWing 1220. 生命之树(树形DP)

在X森林里,上帝创建了生命之树。

他给每棵树的每个节点(叶子也称为一个节点)上,都标了一个整数,代表这个点的和谐值。

上帝要在这棵树内选出一个非空节点集 S,使得对于 S 中的任意两个点 a,b,都存在一个点列 {a,v1,v2,…,vk,b} 使得这个点列中的每个点都是 S 里面的元素,且序列中相邻两个点间有一条边相连。

在这个前提下,上帝要使得 S 中的点所对应的整数的和尽量大。

这个最大的和就是上帝给生命之树的评分。

经过 atm 的努力,他已经知道了上帝给每棵树上每个节点上的整数。

但是由于 atm 不擅长计算,他不知道怎样有效的求评分。

他需要你为他写一个程序来计算一棵树的分数。

输入格式

第一行一个整数 n 表示这棵树有 n 个节点。

第二行 n 个整数,依次表示每个节点的评分。

接下来 n−1 行,每行 2 个整数 u,v,表示存在一条 u 到 v 的边。

由于这是一棵树,所以是不存在环的。

树的节点编号从 1 到 n。

输出格式

输出一行一个数,表示上帝给这棵树的分数。

数据范围

1≤n≤105,
每个节点的评分的绝对值均不超过 106。

输入样例:

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

输出样例:

8

树形DP。设dp[x]为以x为根的子树里包含x的连通块的最大分数,有转移方程\(dp[x] = c[x] + \Sigma max(dp[y], 0)\)

最后答案对所有dp[i]取max即可。

代码瞎写的==写麻烦了

#include <iostream>
#define int long long
#define N 100005
using namespace std;
int n, tot = 0, head[N], ver[2 * N], Next[2 * N];
int c[N];
long long dp[N] = {0}, dp1[N] = {0}; //dp[i]表示以i为根的子树里包含的子联通块的分数最大值 有可能包含i这个点 也可能在i的子树里
bool in[N] = {0};//in[i] = 1 表示i这个点在i为根的子树里包含的最大分数的联通块内
void add(int x, int y)
{
    ver[++tot] = y, Next[tot] = head[x], head[x] = tot;
}
long long ans = -1e14;
void dfs(int x, int pre)
{
    long long now = -1e14;
    for (int i = head[x]; i; i = Next[i])
    {
        int y = ver[i];
        if(y == pre)
            continue;
        dfs(y, x);
        now = max(now, dp[y]);
    }
    dp[x] = now;
    dp1[x] = c[x];
    if (c[x] >= now)
    {
        dp[x] = c[x];
        in[x] = 1;
    }
    long long tmp = c[x];
    for (int i = head[x]; i; i = Next[i])
    {
        int y = ver[i];
        if(in[y] && dp[y] >= 0)
        {
            tmp += 1ll * dp[y];
        }
        if(dp1[y] >= 0)
            dp1[x] += dp1[y];
    }

    if(tmp >= now)
    {
        dp[x] = tmp;
        in[x] = 1;
    }
    ans = max(ans, dp[x]);
    ans = max(ans, dp1[x]);
}
signed main()
{
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> c[i];
    for (int i = 1; i <= n - 1; i++)
    {
        int u, v;
        cin >> u >> v;
        add(u, v);
        add(v, u);
    }
    dfs(1, 0);
    cout << ans;
    return 0;
}
posted @ 2020-11-11 09:34  脂环  阅读(110)  评论(0编辑  收藏  举报