poj2478

时间:2023-03-10 08:26:12
poj2478

比较简单的树形dp;

定义s[i]为节点i的子树节点数和(包括自身);叶子节点s[j]=1;

s[i]=signma(s[k])+1 (k是i的孩子)

则i满足的条件是 1.s[k]<=n div 2  (k为所有孩子节点)

2.n-s[k]<=n div 2;

由于n比较大,可以考虑用前向星来存储,这题想明白了还是很简单的,最后注意满足条件的节点升序输出;

 type link=^node;
     node=record
       data:integer;
       next:link;
     end;
var c:array[..] of link;
    f,a:array[..] of boolean;
    s:array[..] of longint;
    i,n,x,y:integer;
    w:boolean;
    r:link;
procedure add(x,y:integer);    //前向星
  var p:link;
  begin
    new(p);
    p^.data:=y;
    p^.next:=c[x];
    c[x]:=p;
  end;
procedure treedp(x:integer);
  var ch:boolean;
      i:integer;
      r:link;
  begin
    ch:=true;
    s[x]:=;
    f[x]:=true;
    r:=c[x];
    while r<>nil do
    begin
      if not f[r^.data] then
      begin
        f[r^.data]:=true;                    //前向星是图结构,这里的标记是建立从父节点到子节点的关系
        treedp(r^.data);
        if s[r^.data]>n div then ch:=false;   
        inc(s[x],s[r^.data]);
      end;
      r:=r^.next;
    end;
    if (n-s[x])>n div then ch:=false;
    if ch then a[x]:=true;
  end;
begin
  readln(n);
  for i:= to n- do
  begin
    readln(x,y);
    add(x,y);
    add(y,x);
  end;
  fillchar(f,sizeof(f),false);
  fillchar(a,sizeof(a),false);
  treedp();               //生成树任意一个节点都可以作为根节点
  w:=false;
  for i:= to n do
  begin
    if a[i] then
    begin
      w:=true;
      writeln(i);
    end;
  end;
  if not w then writeln('NONE');
end.