其他分享
首页 > 其他分享> > CF1187E Tree Painting

CF1187E Tree Painting

作者:互联网

CF1187E Tree Painting

分析

首先,我们贪心的想,当第一个点确定后,我们所求的最大值就是,依次选择子节点

这样,我们可以用树形DP求出以1为根的树,所能得到的最大权值。

递推公式为

\[f[i] = sz[i] + \sum_{j = son_1}^{son_m}f[j] \]

则,我们可以轻松得到

\[f[1] = n + \sum_{j = son_1}^{son_m}f[j] \]

但是我们需要求出以每个点为根节点能得到的最大值的最大值

当然不难想到,用换根DP啦。

推换根DP的公式

子节点son

分为两部分,前边为原本son下边的,后边的是,将父节点变为子节点后的贡献。

\[g[son] = n + \sum_{j = son_1}^{son_s}f[j] + g[f] - sz[son] - f[son] \]

我们开始对式子进行拼接变形。

\[g[son] = n + \sum_{j = son_1}^{son_s}f[j] + sz[son] - sz[son] + g[f] - sz[son] - f[son] \]

其中分别加sz[son]原因是为了是把那一个Σ处理一下。

式子最后变为

\[g[son] = n + f[son] + sz[son] + g[f] - 2*sz[son] - f[son] \]

\[g[son] = n + sz[son] + g[f] - 2*sz[son] \]

好嘞,直接看代码。

Ac_code

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
int h[N],ne[N<<1],e[N<<1],idx;
LL f[N],g[N],sz[N];
int n;

void add(int a,int b)
{
    e[idx] = b,ne[idx] = h[a],h[a] = idx++;
}

void dfs1(int u,int fa)
{
    sz[u] = 1;
    for(int i=h[u];~i;i=ne[i])
    {
        int j = e[i];
        if(j==fa) continue;
        dfs1(j,u);
        sz[u] += sz[j];
        f[u] += f[j];
    }
    f[u] += sz[u];
}

void dfs2(int u,int fa)
{
    for(int i=h[u];~i;i=ne[i])
    {
        int j = e[i];
        if(j==fa) continue;
        g[j] = g[u] + n - 2 * sz[j];
        dfs2(j,u);
    }
}

int main()
{
    scanf("%d",&n);
    memset(h,-1,sizeof h);
    for(int i=0;i<n-1;i++)
    {
        int u,v;scanf("%d%d",&u,&v);
        add(u,v),add(v,u);
    }
    dfs1(1,-1);
    g[1] = f[1];
    dfs2(1,-1);
    LL ans = 0;
    for(int i=1;i<=n;i++) ans = max(ans,g[i]);
    printf("%lld\n",ans);
    return 0;
}

标签:sz,sum,Tree,son,最大值,CF1187E,Painting,节点,DP
来源: https://www.cnblogs.com/aitejiu/p/16267727.html