【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.
null