冷静 清|

艾特玖

园龄:3年11个月粉丝:12关注:7

CF1187E Tree Painting

CF1187E Tree Painting

分析

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

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

递推公式为

f[i]=sz[i]+j=son1sonmf[j]

则,我们可以轻松得到

f[1]=n+j=son1sonmf[j]

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

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

推换根DP的公式

子节点son

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

g[son]=n+j=son1sonsf[j]+g[f]sz[son]f[son]

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

g[son]=n+j=son1sonsf[j]+sz[son]sz[son]+g[f]sz[son]f[son]

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

式子最后变为

g[son]=n+f[son]+sz[son]+g[f]2sz[son]f[son]

g[son]=n+sz[son]+g[f]2sz[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;
}

本文作者:艾特玖

本文链接:https://www.cnblogs.com/aitejiu/p/16267727.html

版权声明:本作品采用艾特玖许可协议进行许可。

posted @   艾特玖  阅读(20)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起