2017年8月7日提高组T1 根
Description
一天,小B得到了一棵n个节点的树。无聊至极的小B想要找出一个点,使得以这个点为根时,所有点的深度之和最大。但小B打开手机,发现他最爱的re:creator又更新啦,于是这个无聊的任务就交给你了。
Input
第一行一个数n,接下来n-1行,每行两个数,表示一条边。
Output
一行一个整数,表示所有点深度之和的最大值的那个点。
如果最大值相同,输出拥有更小编号的点
分析:先求出以1为根所有节点的子树大小,然后求出此时深度和(dfs实现),最后从1的儿子开始换根,deep[son]=deep[fa]-f[son]+n-f[fa],f[i]表示i节点的子树大小。
代码
#include <cstdio>
#define maxn 2000000
using namespace std;
struct edge
{
int p,q,next;
}a[maxn];
int n,ans,max,f[maxn],ls[maxn],ls1[maxn],x1[maxn],y1[maxn],next1[maxn];
int l,l1;
bool v[maxn];
void add(int x,int y)
{
l++;
a[l].next=ls[x];
ls[x]=l;
a[l].p=x;
a[l].q=y;
}
int dfs(int x,int dep)
{
v[x]=true;
max+=dep;
for (int i=ls[x];i;i=a[i].next)
if (!v[a[i].q])
{
l1++;
x1[l1]=x;
y1[l1]=a[i].q;
next1[l1]=ls1[x];
ls1[x]=l1;
f[x]+=dfs(a[i].q,dep+1)+f[a[i].q];
}
return 1;
}
void dfs1(int x,int s)
{
v[x]=true;
if (s>max)
{
ans=x;
max=s;
}
if (max==s&&x<ans) ans=x;
for (int i=ls1[x];i;i=next1[i])
if (!v[y1[i]]&&y1[i]!=0)
{
dfs1(y1[i],s-f[y1[i]]+(n-f[y1[i]]));
}
}
int main()
{
scanf("%d",&n);
for (int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
dfs(1,1);
ans=1;
for (int i=1;i<=n;i++)
{
v[i]=false;
f[i]++;
}
dfs1(1,max);
printf("%d",ans);
}