Description
一天,小B得到了一棵n个节点的树。无聊至极的小B想要找出一个点,使得以这个点为根时,所有点的深度之和最大。但小B打开手机,发现他最爱的re:creator又更新啦,于是这个无聊的任务就交给你了。
Input
第一行一个数n,接下来n-1行,每行两个数,表示一条边。
Output
一行一个整数,表示所有点深度之和的最大值的那个点。
如果最大值相同,输出拥有更小编号的点
Sample Input
5
2 1
3 1
4 2
5 3
Sample Output
4
Hint
对于前30%的数据,n<=1000.
对于前100%的数据,n<=1000000.
思路
dfs一次只有就可以o(1)换根的。
代码
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
#include<algorithm>
#define N 3000000
using namespace std;
struct NOTE{
int x,y,next;
}e[N];
int head[N];
int low[N];
int maxn,ans,dep,n;
int tot;
void add(int x,int y)
{
e[++tot]=(NOTE){x,y,head[x]},head[x]=tot;
e[++tot]=(NOTE){y,x,head[y]},head[y]=tot;
}
void dfs(int x,int r,int d)
{
dep+=d;
low[x]=1;
for (int i=head[x];i!=0;i=e[i].next)
{
if (e[i].y==r) continue;
dfs(e[i].y,x,d+1);
low[x]+=low[e[i].y];
}
}
void find(int x,int r,int dep)
{
if (x!=1)
{
dep=dep-low[x]+(n-low[x]);
if ((dep>maxn)||((dep==maxn)&&(ans>x)))
{
maxn=dep;
ans=x;
}
}
for (int i=head[x];i!=0;i=e[i].next)
{
if (e[i].y==r) continue;
find(e[i].y,x,dep);
}
}
int main()
{
tot=1;
scanf("%d",&n);
for (int i=1;i<=n-1;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
}
dfs(1,0,0);
maxn=dep;
ans=1;
find(1,0,dep);
printf("%d",ans);
}