树型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.