题目大意
有个公司要举行一场晚会。为了能玩得开心,公司领导决定:如果邀请了某个人,那么一定不会邀请他的上司(上司的上司,上司的上司的上司……都可以邀请)。每个参加晚会的人都能为晚会增添一些气氛,求一个邀请方案,使气氛值的和最大(气氛值=邀请的人的气氛总值)。
分析
定义f[I,0]表示不邀请节点i能够取得的最大值,f[I,1]表示邀请节点i能够取得的最大值。
一开始以上司为父节点,下属为叶子节点。同时设一个总根节点N+1。连着各种没有上司的boss.
动态转移方程为
F[I,0]=max{f[I,0],f[I,0]+max(f[I.son,0],f[i.son,1])}
F[I,1]=max{f[I,1],f[I,1]+f[I,son,0]}+w[i]
son为子节点。
最后输出f[n+1,0]
代码
var
a:array[0..7000,0..7000] of longint;
f:array[0..7000,0..1] of longint;
w:array[0..7000] of longint;
v,b:array[0..7000] of boolean;
i,j,k,l:longint;
n,m:longint;
procedure dfs(r:longint);
var
i,j,k:longint;
c:longint;
begin
v[r]:=false;
if a[r,0]=0
then
begin
f[r,0]:=0;
f[r,1]:=w[r];
exit;
end;
for i:=1 to a[r,0] do
if v[a[r,i]] then dfs(a[r,i]);
for i:=1 to a[r,0] do
begin
c:=a[r,i];
if f[c,1]>f[c,0]
then f[r,0]:=f[r,0]+f[c,1]
else f[r,0]:=f[r,0]+f[c,0];
f[r,1]:=f[r,1]+f[c,0];
end;
f[r,1]:=f[r,1]+w[r];
end;
begin
readln(n);
fillchar(v,sizeof(v),1);
for i:=1 to n do
readln(w[i]);
readln(j,k);
repeat
if j+k=0 then break;
inc(a[k,0]);
b[j]:=true;
a[k,a[k,0]]:=j;
readln(j,k);
until false;
for i:=1 to n do
begin
if not b[i]
then
begin
inc(a[n+1,0]);
a[n+1,a[n+1,0]]:=i;
end;
end;
dfs(n+1);
write(f[n+1,0]);
end.