题目大意:给出一个N个点的树,找出一个点来,以这个点为根的树时,所有点的深度之和最大,N<=1000000
考虑一个点向其儿子转移对答案的影响。该子树内所有点深度-1,除该子树外的点深度+1,所以随便选一个根,预处理出深度和,然后全都转移一遍就可以。
自己的代码:
#include<cstdio>
#include<algorithm>
#define gm 1000001
using namespace std;
int n;
struct e
{
int t;
e* n;
e(int t,e* n):t(t),n(n){}
}*f[gm];
long long ans=0;
int nd;
int sz[gm],fat[gm];
void dfs1(int x,int d)
{
sz[x]=1;
ans+=d;
for(e *i=f[x];i;i=i->n)
{
if(fat[x]==i->t) continue;
fat[i->t]=x;
dfs1(i->t,d+1);
sz[x]+=sz[i->t];
}
}
void dfs2(int x,long long v)
{
if(ans<v||v==ans&&x<nd) ans=v,nd=x;
for(e *i=f[x];i;i=i->n)
{
if(fat[x]==i->t) continue;
dfs2(i->t,v-(sz[i->t]<<1)+n);
}
}
int main()
{
scanf("%d",&n);
int a,b;
for(int i=1;i<n;i++)
scanf("%d%d",&a,&b),f[a]=new e(b,f[a]),f[b]=new e(a,f[b]);
srand(114514);
int r=rand()%n+1;
nd=r;
dfs1(r,0);
dfs2(r,ans);
printf("%d",nd);
return 0;
}