题干
给出一个N个点的树,找出一个点来,以这个点为根的树时,所有点的深度之和最大
Input
给出一个数字N,代表有N个点.N<=1000000 下面N-1条边.
Output
输出你所找到的点,如果具有多个解,请输出编号最小的那个.
Example
8
1 4
5 6
4 5
6 7
6 8
2 4
3 4
7
简单粗暴的题意,直接莽就完事了。
先搞个小点的例子试试水(我是把根节点的深度设为了0,其实你设1设几都没关系)
简单明了对吧,那我把根换一下呢?
我们会发现,我们把3作为根,那么包括3在内的3的子树的深度都减小了1,而1和2的深度都增加了1。那么规律是不是显而易见:
ans[儿砸]=(ans[爹]-siz[儿砸] )+(n-siz[儿砸] )
直接两遍dfs,第一遍处理完siz[]和ans[1](我们第一遍默认以1为根,当然你以别的为根也不是不行),第二遍再按找到的规律dfs更新答案即可
代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
const int maxn=1000000+10;
long long head[maxn],len=0,ans[maxn],siz[maxn];
long long maxx;
int n,flag;
struct Edge{
int next,to;
}edge[maxn<<1];
void Add(int u,int v){
edge[++len].to=v;
edge[len].next=head[u];
head[u]=len;
}
void Dfs1(int u,int fa,int dep){
siz[u]=1;
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;
if(v==fa) continue;
Dfs1(v,u,dep+1);
siz[u]+=siz[v];
ans[1]+=dep+1;
}
}
void Dfs2(int u,int fa){
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].to;
if(v==fa) continue;
ans[v]=ans[u]+n-2*siz[v];
if(ans[v]>maxx){
maxx=ans[v];
flag=v;
}
else if(ans[v]==maxx&&flag>v){
flag=v;
}
Dfs2(v,u);
}
}
int main(){
cin>>n;
for(int i=1;i<n;i++){
int u,v;
scanf("%d%d",&u,&v);
Add(u,v),Add(v,u);
}
Dfs1(1,0,0);
maxx=ans[1],flag=1;
Dfs2(1,0);
cout<<flag<<endl;
return 0;
}