题意:
给定一棵树,树上每个节点都是白色.
操作:可以选择一个节点涂黑,然后加上它的子节点的数目的值(包括自身)
直到涂满整棵树,求能获得的最大值
解析:
树形dp换根,两个dfs
第一个dfs求各节点的子节点数目,第二个dfs换根,每次换相邻节点的为根.siz(v)是为根的节点子节点数,n-siz(v)是是v->u方向的子节点数,即siz(u)
sum(v)=sum(u)+(n-siz(v))-siz(v),取最大值即可
ac:
#include<bits/stdc++.h>
#define ll long long
#define MAXN 400005
using namespace std;
int to[MAXN],next1[MAXN],head[MAXN];
int tot=0,n;
int siz[MAXN];
ll ans;
void add(int u,int v)
{
to[++tot]=v;
next1[tot]=head[u];
head[u]=tot;
}
void dfs(int u,int fa)
{
siz[u]=1;
for(int i=head[u];i;i=next1[i])
{
int v=to[i];
if(v==fa)
continue;
dfs(v,u);
siz[u]+=siz[v];
}
}
void dfs2(int u,int fa,ll sum)
{
ans=max(ans,sum);
for(int i=head[u];i;i=next1[i])
{
int v=to[i];
if(v==fa)
continue;
ll kk=sum+(n-siz[v])-siz[v];
dfs2(v,u,kk);
}
}
int main()
{
int u,v;
scanf("%d",&n);
for(int i=1;i<n;i++)
{
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
dfs(1,-1);
ll sum=0;
for(int i=1;i<=n;i++)
sum+=siz[i];
ans=-1;
dfs2(1,-1,sum);
printf("%lld\n",ans);
return 0;
}