二*苹果树 树型动态规划

题目大意

  对于一个二叉树,除根节点外,每个节点都有相应的一个权值。在此基础上,求保留多少个点使得其仍然满足树的性质且权值总和最大。

 

分析

  先建树。

  ch[v,1],ch[v,2]分别存V节点的左右孩子。dp[v,l]存以V为根的树保留L个节点的最大权和。Num[v]为点v的权值。

  dp[v,l]=max{dp[ch[v,1],j]+dp[ch[v,2],l-j-1]+num[v]} (0<=j<=l-1)

这里特别指出,为了使其仍然为二叉树,我们一定要保留根节点,因此j<=l-1。

  然后,可以减枝。

  然后2,注意边界:

    如果l=0,那么dp[v,l]=0。

    如果点v没有孩子,那么dp[v,l]=v的权值。

  然后3,因为输入的是要保留m条边,而转化后的题目是保留nm个点,所以输入的m要加1.

 

代码

var
  f:array[0..200,0..200] of longint;
  a:array[0..200,1..3] of longint;
  b:array[0..200,0..200] of longint;
  v,num:array[0..200] of longint;
  i,j,k,l:longint;
  n,m:longint;
  ans:longint;

procedure make(v:longint);
var
  i,j,k:longint;
begin
  for i:=1 to n do
    begin
      if b[v,i]>0 then
        begin
          a[v,1]:=i;
          num[i]:=b[v,i]-1;
          b[v,i]:=-1; b[i,v]:=-1;
          make(i);
          break;
        end;
    end;
  for i:=1 to n do
    begin
      if b[v,i]>0 then
        begin
          a[v,2]:=i;
          num[i]:=b[v,i]-1;
          b[v,i]:=-1; b[i,v]:=-1;
          make(i);
          break;
        end;
    end;
end;

procedure dfs(r,l:longint);
var
  i,j,k:longint;
begin
  if f[r,l]<>0 then exit;
  if l=0
    then
      begin
        f[r,l]:=0;
        exit;
      end;
  if (a[r,1]=0) and (a[r,2]=0)
    then begin
      f[r,l]:=num[r];
      exit;
    end;
  for i:=0 to l-1 do
    begin
      dfs(a[r,1],i);
      dfs(a[r,2],l-i-1);
      if f[r,l]<f[a[r,1],i]+f[a[r,2],l-i-1]+num[r]
        then
          f[r,l]:=f[a[r,1],i]+f[a[r,2],l-i-1]+num[r];
    end;
end;

begin
  readln(n,m);
  m:=m+1;
  for i:=1 to n-1 do
    begin
      readln(j,k,l);
      b[j,k]:=l+1;
      b[k,j]:=l+1;
    end;
  fillchar(f,sizeof(f),0);
  fillchar(v,sizeof(v),0);
  fillchar(a,sizeof(a),0);
  v[0]:=1;
  make(1);
  dfs(1,m);
  writeln(f[1,m]);
end.


posted @ 2016-05-05 20:42  一个响亮的蒟蒻  阅读(194)  评论(0编辑  收藏  举报