没有上司的舞会 Codevs1380&POj2342&Hdu1520

树型Dp入门经典题=w=

显然,贪心是不对的,因为如果一个节点不选的话,它的儿子不一定 一定要选而可能去选它的孙子节点

对于一个节点,我们有选与不选两种状态,我们用f[i,1]表示对于i节点这棵树,选i节点的最大值,f[i,0]表示不选i节点的最大值,v[i]表示i的快乐度

所以一不小心,dp方程的身影就这样若隐若现

         f[i,0]=max{f[j,0],f[j,1]}(j表示i的儿子节点)

         f[i,1]=v[i]+f[j,0]

然后就可以了=w=

网上大部分题解采用的是链表存储i的儿子节点,这里采用的是邻接表来存(链表暂时打的不太顺手=。=)

注意,hdu1520 是多组数据,要用 not EOF 判断,然而题目中没有任何提示=A=(我就被这个坑了一节课一直Wa),不过Codevs和POj不存在这个问题直接交就行=w=

下面的代码为非多组数据的

<pre name="code" class="plain">var
    n,a,b,l             :longint;
    f                   :array[0..6010,0..2] of longint;
    v,pre,other,last    :array[0..6010] of longint;
    flag                :array[0..6010] of boolean;
    i                   :longint;
function max(a,b:longint):Longint;
begin
   if a<b then exit(b) else exit(a);
end;

procedure connect(x,y:longint);
begin
   inc(l);
   pre[l]:=last[x];
   last[x]:=l;
   other[l]:=y;
end;

procedure dfs(x:longint);
var
    p,q:longint;
begin
   q:=last[x];
   if (q=0) then
   begin
      f[x,1]:=v[x];
      f[x,0]:=0;
      exit;
   end;
   f[x,1]:=v[x];
   while (q<>0) do
   begin
      p:=other[q];
      dfs(p);
      f[x,1]:=f[x,1]+f[p,0];
      f[x,0]:=f[x,0]+max(f[p,0],f[p,1]);
      q:=pre[q];
   end;
end;

begin
   read(n);
   for i:=1 to n do read(v[i]);
   read(a,b);
   while (a<>0) or (b<>0) do
   begin
      flag[a]:=true;
      connect(b,a);
      read(a,b);
   end;
   for i:=1 to n do
    if not flag[i] then break;
   dfs(i);
   writeln(max(f[i,0],f[i,1]));
end.


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值