jzoj. 1301. treecut

来源:互联网 发布:windows 7 原版下载 编辑:程序博客网 时间:2024/06/05 14:57

Description

  有一个N个节点的无根树,各节点编号为1..N,现在要求你删除其中的一个点,使分割开的连通块中节点个数都不超过原来的一半多。

Input

  第一行:一个整数N (1 <= N <= 10,000)。   后面有N-1行:每行两个整数 X 和 Y,表示一个边连接的两个节点号。

Output

  输出所有可能选择的点。如果有多个节点,按编号从小到大输出,每个一行。 如果找不到这样的点,输出一行:”NONE”.

Sample Input

10
1 2
2 3
3 4
4 5
6 7
7 8
8 9
9 10
3 8

Sample Output

3 8

Data Constraint

Hint

样例说明:   删除3号或8号节点,则分枝最多有5个节点

分析:看完题目,应该知道怎么做了吧。把一个点删去,就会产生的连通块包括它每个儿子和除了它为根的子树外的其他点。我们可以深搜跑出每个点的子树的节点数,判断一下就好。因为是无根数,把1看做root就好了。

代码:

const maxn=10001;type node=record  y,next:longint;end;var g:array [1..maxn*2] of node; f,ls:array [1..maxn] of longint; b,v:array [1..maxn] of boolean; n,i,j,x,y:longint; fe:boolean;procedure dfs(x:longint); var t,y:longint;     flag:boolean;begin t:=ls[x]; while t>0 do    begin     y:=g[t].y;     if v[y]=false then      begin       v[y]:=true;       dfs(y);       f[x]:=f[x]+f[y];       if f[y]>n div 2 then b[x]:=false;      end;     t:=g[t].next;  end; f[x]:=f[x]+1; if (n-f[x]>n div 2) then b[x]:=false;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; fillchar(b,sizeof(b),true); v[1]:=true; dfs(1); fe:=true; for i:=1 to n do  if b[i] then begin writeln(i,' '); fe:=false; end; if fe then writeln('NONE');end.