没有上司的舞会 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=

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

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 a0) 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.

没有上司的舞会 Codevs1380&POj2342&Hdu1520_第1张图片

你可能感兴趣的:(树型DP)