【NOIP2016练习】T3 tree (树形DP)

题意:一棵有N个结点的树,每个节点上有权值c[i]

         需要选出若干结点,对于任意结点他的所有祖先都被选取且选取总个数不能超过lim  

         在此前提下使权值和最大

         n,lim<=3000

 

思路:WA了1次才过真是傻

        f[i,j]表示选取I为根,取J个结点的最大值

        用类似背包的转移,注意dp[u,i]I不能取0,因为U必取

        

 1 var dp:array[1..3000,0..3000]of longint;
 2     c:array[1..3000]of longint;
 3     head,vet,next,flag,de:array[1..10000]of longint;
 4     n,lim,tot,i,j,ans,x,y:longint;
 5 
 6 procedure add(a,b:longint);
 7 begin
 8  inc(tot);
 9  next[tot]:=head[a];
10  vet[tot]:=b;
11  head[a]:=tot;
12 end;
13 
14 function min(x,y:longint):longint;
15 begin
16  if x<y then exit(x);
17  exit(y);
18 end;
19 
20 function max(x,y:longint):longint;
21 begin
22  if x>y then exit(x);
23  exit(y);
24 end;
25 
26 procedure dfs(u:longint);
27 var e,v,i,j:longint;
28 begin
29  flag[u]:=1; de[u]:=1;
30  e:=head[u]; dp[u,0]:=0; dp[u,1]:=c[u];
31 
32  e:=head[u];
33  while e<>0 do
34  begin
35   v:=vet[e];
36   if flag[v]=0 then
37   begin
38    dfs(v);
39    de[u]:=de[u]+de[v];
40    for i:=min(lim,de[u]) downto 2 do
41     for j:=0 to min(lim,de[v]) do
42      if i-j>=1 then dp[u,i]:=max(dp[u,i],dp[u,i-j]+dp[v,j]);
43   end;
44   e:=next[e];
45  end;
46  {write(u,' ');
47  for i:=0 to lim do write(dp[u,i],' ');
48  writeln;  }
49 end;
50 
51 begin
52  assign(input,'1.in'); reset(input);
53  assign(output,'1.out'); rewrite(output);
54  readln(n,lim);
55  for i:=1 to n do read(c[i]);
56  for i:=1 to n-1 do
57  begin
58   readln(x,y);
59   add(x,y);
60   add(y,x);
61  end;
62  for i:=1 to n do
63   for j:=0 to lim do dp[i,j]:=-maxlongint div 3;
64  dfs(1);
65  ans:=-maxlongint;
66  for j:=0 to min(de[1],lim) do ans:=max(ans,dp[1,j]);
67  writeln(ans);
68  close(input);
69  close(output);
70 end.

 

posted on 2016-10-30 19:31  myx12345  阅读(213)  评论(0编辑  收藏  举报

导航