没有上司的晚会 树形动态规划

题目大意

  有个公司要举行一场晚会。为了能玩得开心,公司领导决定:如果邀请了某个人,那么一定不会邀请他的上司(上司的上司,上司的上司的上司……都可以邀请)。每个参加晚会的人都能为晚会增添一些气氛,求一个邀请方案,使气氛值的和最大(气氛值=邀请的人的气氛总值)。

 

分析

  定义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.


posted @ 2016-05-10 17:27  一个响亮的蒟蒻  阅读(238)  评论(0编辑  收藏  举报