这题用换根DP非常好处理。
先用(1)为根树形DP出第一个把(1)号点变成黑点所得到的贡献。然后发现若(x)的答案为(a[x])且(v)为(x)的子节点,那么(a[v]=a[x]+n-2 imes siz[v])(换根过程)。
然后对每个点的答案去一个最大值就好了。
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=200009;
int n,head[N],cnt,siz[N];
LL fuck[N],ans,a[N];
struct Edge
{
int nxt,to;
}g[N*2];
void add(int from,int to)
{
g[++cnt].nxt=head[from];
g[cnt].to=to;
head[from]=cnt;
}
void init()
{
scanf("%d",&n);
int x,y;
for (int i=1;i<n;i++)
scanf("%d %d",&x,&y),add(x,y),add(y,x);
}
void dfs(int x,int fa)
{
siz[x]=1;
for (int i=head[x];i;i=g[i].nxt)
{
int v=g[i].to;
if(v==fa)
continue;
dfs(v,x);
siz[x]+=siz[v];
fuck[x]+=fuck[v];
}
fuck[x]+=siz[x];
}
void DFS(int x,int fa)
{
for (int i=head[x];i;i=g[i].nxt)
{
int v=g[i].to;
if(v==fa)
continue;
a[v]=a[x]-siz[v]+n-siz[v];
ans=max(ans,a[v]);
DFS(v,x);
}
}
void work()
{
dfs(1,-1);
ans=a[1]=fuck[1];
DFS(1,-1);
printf("%lld
",ans);
}
int main()
{
init();
work();
return 0;
}