2017年8月7日提高组T1 根

67 篇文章 1 订阅
26 篇文章 0 订阅

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.

分析:
首先我们对于一组转移,从x转移到y,设x为原来的根,且x与y有边相连,有只有y的子树的深度变小1,其他点的深度都变大1,包括x节点从0深度到1深度。我们预处理出以1为根的树的深度和,和每个节点为根的子树的节点数,转移显然。
设dep[x]为以x为根的数的深度和,有
dep[y]=dep[x]-f[y]+(n-f[y])
在所有的dep中取最大值即可。
注意:树的边为双向边,注意空间。

代码:

const
 maxn=1000001;

type
 node=record
  y,next:longint;
end;

var
 g:array [1..maxn*2] of node;
 f,ls:array [1..maxn] of longint;
 v:array [1..maxn] of boolean;
 n,i,j,x,y,ans,tt,s:longint;

procedure dfs(x:longint;dep:longint);
 var t,y:longint;
begin
 t:=ls[x];
 while t>0 do
    begin
     y:=g[t].y;
     if v[y]=false then
      begin
       v[y]:=true;
       dfs(y,dep+1);
       f[x]:=f[x]+f[y];
      end;
     t:=g[t].next;
  end;
 f[x]:=f[x]+1;
 ans:=ans+dep;
end;

procedure dfss(x:longint;s:longint);
 var t,y,q:longint;
begin
 t:=ls[x];
 while t>0 do
    begin
     y:=g[t].y;
     if v[y]=false then
      begin
       v[y]:=true;
       q:=s-f[y]+n-f[y];
       if (q>ans) or ((q=ans) and (y<tt)) then
        begin
         ans:=q;
         tt:=y;
        end;
       dfss(y,q);
      end;
     t:=g[t].next;
  end;
end;

begin
 read(n);
 for i:=1 to n-1 do
  begin
   read(x,y);
   g[i].y:=y;
   g[i].next:=ls[x];
   ls[x]:=i;
   g[i+n].y:=x;
   g[i+n].next:=ls[y];
   ls[y]:=i+n;
  end;
 v[1]:=true;
 dfs(1,0);
 fillchar(v,sizeof(v),false);
 v[1]:=true;
 tt:=1;
 dfss(1,ans);
 writeln(tt);
end.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值