比较好的树形dp,涉及到树上路径的题目,我们往往考虑对路径分类

当我们考虑以x为根的子树,有这样几类路径

1. 起点终点都在子树内

2. 一个点延伸到子树外

对于要选择另一个点在子树外的路径,要建立在不破坏儿子子树内的路径基础上

因为破坏会破坏多条,而只能多选择一条,不合适

因此我们考虑树dp,设f[x]为路径起点终点在子树内能选择的最多路径数目,d[x]表示还没用过的另一个点在x子树外的路径的集合

我们知道,对于x的每个孩子d,d[y]中最多只会有1条路径被选中,因此我们可以用状压dp解决

  1 type node=record
  2        po,next:longint;
  3      end;
  4 
  5 var a:array[0..1200,0..1200] of longint;
  6     w:array[0..1010,0..1010] of boolean;
  7     e:array[0..2400] of node;
  8     g,f,q,b,s,p:array[0..1200] of longint;
  9     len,i,tt,n,m,x,y:longint;
 10 
 11 function max(a,b:longint):longint;
 12   begin
 13     if a>b then exit(a) else exit(b);
 14   end;
 15 
 16 procedure add(x,y:longint);
 17   begin
 18     inc(len);
 19     e[len].po:=y;
 20     e[len].next:=p[x];
 21     p[x]:=len;
 22   end;
 23 
 24 function check(x,y:longint):boolean;
 25   var i,j:longint;
 26   begin
 27     for i:=1 to s[x] do
 28       for j:=1 to s[y] do
 29         if w[a[x,i],a[y,j]] then exit(true);
 30     exit(false);
 31   end;
 32 
 33 procedure dfs(x,fa:longint);
 34   var st,mx,i,y,t,j,k:longint;
 35   begin
 36     f[x]:=0;
 37     s[x]:=1;
 38     a[x,s[x]]:=x;
 39     i:=p[x];
 40     while i<>0 do
 41     begin
 42       y:=e[i].po;
 43       if y<>fa then
 44         dfs(y,x);
 45       i:=e[i].next;
 46     end;
 47     i:=p[x];
 48     t:=0;
 49     while i<>0 do
 50     begin
 51       y:=e[i].po;
 52       if y<>fa then
 53       begin
 54         f[x]:=f[x]+f[y];
 55         if check(x,y) then inc(f[x])
 56         else begin
 57           inc(t);
 58           q[t]:=y;
 59         end;
 60       end;
 61       i:=e[i].next;
 62     end;
 63     k:=0;
 64     for i:=1 to t-1 do
 65       for j:=i+1 to t do
 66         if check(q[i],q[j]) then
 67         begin
 68           inc(k);
 69           b[k]:=(1 shl (i-1)) or (1 shl (j-1));
 70         end;
 71     st:=0;
 72     mx:=0;
 73     for i:=0 to 1 shl t-1 do
 74     begin
 75       g[i]:=0;
 76       for j:=1 to k do
 77         if b[j] and i=b[j] then
 78           g[i]:=max(g[i],g[i xor b[j]]+1);
 79       if g[i]>mx then
 80       begin
 81         mx:=g[i];
 82         st:=0;
 83       end;
 84       if g[i]=mx then st:=st or ((1 shl t-1) xor i);
 85     end;
 86     f[x]:=f[x]+mx;
 87     for i:=1 to t do
 88       if (1 shl (i-1)) and st>0 then
 89       begin
 90         y:=q[i];
 91         for j:=1 to s[y] do
 92         begin
 93           inc(s[x]);
 94           a[x,s[x]]:=a[y,j];
 95         end;
 96       end;
 97   end;
 98 
 99 begin
100   readln(tt);
101   while tt>0 do
102   begin
103     dec(tt);
104     len:=0;
105     fillchar(p,sizeof(p),0);
106     readln(n);
107     for i:=1 to n-1 do
108     begin
109       readln(x,y);
110       add(x,y);
111       add(y,x);
112     end;
113     readln(m);
114     fillchar(w,sizeof(w),false);
115     for i:=1 to m do
116     begin
117       readln(x,y);
118       w[x,y]:=true;
119       w[y,x]:=true;
120     end;
121     dfs(1,0);
122     writeln(f[1]);
123   end;
124 end.
View Code

 

posted on 2015-06-20 15:37  acphile  阅读(288)  评论(0编辑  收藏  举报