没有上司的晚会 树形动态规划
题目大意
有个公司要举行一场晚会。为了能玩得开心,公司领导决定:如果邀请了某个人,那么一定不会邀请他的上司(上司的上司,上司的上司的上司……都可以邀请)。每个参加晚会的人都能为晚会增添一些气氛,求一个邀请方案,使气氛值的和最大(气氛值=邀请的人的气氛总值)。
分析
定义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.