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比较大,可以考虑用前向星来存储,这题想明白了还是很简单的,最后注意满足条件的节点升序输出;

 1 type link=^node;
 2      node=record
 3        data:integer;
 4        next:link;
 5      end;
 6 var c:array[0..10010] of link;
 7     f,a:array[0..10010] of boolean;
 8     s:array[0..10010] of longint;
 9     i,n,x,y:integer;
10     w:boolean;
11     r:link;
12 procedure add(x,y:integer);    //前向星
13   var p:link;
14   begin
15     new(p);
16     p^.data:=y;
17     p^.next:=c[x];
18     c[x]:=p;
19   end;
20 procedure treedp(x:integer);
21   var ch:boolean;
22       i:integer;
23       r:link;
24   begin
25     ch:=true;
26     s[x]:=1;
27     f[x]:=true;
28     r:=c[x];
29     while r<>nil do
30     begin
31       if not f[r^.data] then
32       begin
33         f[r^.data]:=true;                    //前向星是图结构,这里的标记是建立从父节点到子节点的关系
34         treedp(r^.data);
35         if s[r^.data]>n div 2 then ch:=false;   
36         inc(s[x],s[r^.data]);
37       end;
38       r:=r^.next;
39     end;
40     if (n-s[x])>n div 2 then ch:=false;
41     if ch then a[x]:=true;
42   end;
43 begin
44   readln(n);
45   for i:=1 to n-1 do
46   begin
47     readln(x,y);
48     add(x,y);
49     add(y,x);
50   end;
51   fillchar(f,sizeof(f),false);
52   fillchar(a,sizeof(a),false);
53   treedp(1);               //生成树任意一个节点都可以作为根节点
54   w:=false;
55   for i:=1 to n do
56   begin
57     if a[i] then
58     begin
59       w:=true;
60       writeln(i);
61     end;
62   end;
63   if not w then writeln('NONE');
64 end.
View Code
原文地址:https://www.cnblogs.com/phile/p/4473309.html