大意
给一棵树,初始时结点都为白色,然后你可以选一个点作为根节点,加上这个节点连通的白色节点数,然后把这个点染黑。下面再继续选择与黑节点相连的点,加上白色节点数,染黑。求最大的值。
思路
那么我们很容易意识到,起关键作用的就是选择了那个根节点。设dp[i]为以i为根节点的最大值。则,我们对于一个根节点,如点1,记sum[i]为i节点子树的个数,则
$ dp[1]=sum[1]+sum[2]+...+sum[n] $
那么转移到下一个点,如2号点,有:
$ dp[2]=sum[1]+sum[3]+sum[4]+...+sum[n]+(sum[1]-sum[2]) $
很显然,每次换根后,需要 $ -2*sum[to]+sum[1] $,2次搜索即可
Code
AC代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll son[200005];
ll all,ans;
vector<int>vec[200005];
void dfs1(int now,int fa,int dep){
all+=dep;
son[now]=1;
for(int i=0;i<vec[now].size();i++){
int to=vec[now][i];
if(to!=fa){
dfs1(to,now,dep+1);
son[now]+=son[to];
}
}
}
void dfs2(int now,int fa,ll val){
ans=max(ans,val);
for(int i=0;i<vec[now].size();i++){
int to=vec[now][i];
if(to!=fa){
dfs2(to,now,val-2ll*son[to]+son[1]);
}
}
}
int main(){
all=0,ans=0;
int n,a,b;
scanf("%d",&n);
for(int i=1;i<n;i++){
scanf("%d%d",&a,&b);
vec[a].push_back(b);
vec[b].push_back(a);
}
dfs1(1,1,1);
dfs2(1,1,all);
printf("%lld\n",ans);
return 0;
}