给出一个N个点的树,找出一个点来,以这个点为根的树时,所有点的深度之和最大
n ≤ 1000000
https://www.luogu.org/problemnew/show/P3478
对于这种挑一个最优点的问题,我们往往先找一个点,计算出其相应的值,在考虑转移到其相邻的点上去。
状态:f[i]表示以i为根时的答案。
初始化:f[1]等于以1为根所有点深度之和。
转移:u是v的父亲,f[u]的值已经求出,把根从u转到v。就相当于v的子树中的点深度都减小了1,其他点深度增加了1。size数组表示子树的大小(点的个数)。变化量为(n-size[v])+(-size[v])。f[v]=f[u]+n-2*size[v]。
结果:在所有f[1~n]中取最大值。
#include<iostream>
#include<cstdio>
#include<algorithm>
#define ll long long
using namespace std;
inline int r()
{
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
const int maxn=1000001;
struct node
{
int next,to;
}e[maxn<<1];
int cnt,id,n;
int head[maxn];
ll f[maxn],dep[maxn],size[maxn],ans;
inline void add(int x,int y)
{
e[++cnt].next=head[x];
e[cnt].to=y;
head[x]=cnt;
}
inline void dfs(int u,int fa)
{
size[u]=1;
dep[u]=dep[fa]+1;
for(int i=head[u];i;i=e[i].next){
if(e[i].to!=fa){
dfs(e[i].to,u);
size[u]+=size[e[i].to];
}
}
}
inline void DFS(int u,int fa)
{
for(int i=head[u];i;i=e[i].next){
if(e[i].to!=fa){
f[e[i].to]=f[u]+n-size[e[i].to]-size[e[i].to];
DFS(e[i].to,u);
}
}
}
int main()
{
n=r();
for(int i=1;i<=n-1;i++){
int x=r(),y=r();
add(x,y);add(y,x);
}
dfs(1,1);
for(int i=1;i<=n;i++){
f[1]+=dep[i];
}
DFS(1,1);
for(int i=1;i<=n;i++){
if(f[i]>ans){
ans=f[i];
id=i;
}
}
printf("%d",id);
return 0;
}