CF1187E Tree Painting
分析
首先,我们贪心的想,当第一个点确定后,我们所求的最大值就是,依次选择子节点
这样,我们可以用树形DP求出以1
为根的树,所能得到的最大权值。
递推公式为
则,我们可以轻松得到
但是我们需要求出以每个点为根节点能得到的最大值的最大值
当然不难想到,用换根DP啦。
推换根DP的公式
子节点son
分为两部分,前边为原本son
下边的,后边的是,将父节点变为子节点后的贡献。
我们开始对式子进行拼接变形。
其中分别加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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步