皇宫看守 树型动态规划

题目大意

  太平王世子事件后,陆小凤成了皇上特聘的御前一品侍卫。 
  皇宫以午门为起点,直到后宫嫔妃们的寝宫,呈一棵树的形状;某些宫殿间可以互相望见。大内保卫森严,三步一岗,五步一哨,每个宫殿都要有人全天候看守,在不同的宫     殿安排看守所需的费用不同。 
  可是陆小凤手上的经费不足,无论如何也没法在每个宫殿都安置留守侍卫。帮助陆小凤布置侍卫,在看守全部宫殿的前提下,使得花费的经费最少。

 

分析

  首先定义:     

    F[T,1] 表示在x点放置守卫的最小费用    

    F[T,2] 表示在x点不放置守卫,同时x点可以或没有儿子节点可以监视到

    F[T,3] 表示在x点不放置守卫,同时x点一定要给儿子节点监视到

  转移方程为F[x,1]=sigma{min(F[y,1],F[y,2],F[y,3])}+w[x]

            F[x,2]=sigma{min(F[y,1],F[y,3])}

            F[x,3]=sigma{min(F[z,1],F[z,3])+F[y,1]}  y<>z  y,z分别为x的子节点                      

  具体见:http://blog.csdn.net/fisher_jiang/article/details/2488506

  

代码

  

var
  a:array[0..7000,0..7000] of longint;
  f:array[0..7000,0..2] of longint;
  w:array[0..7000] of longint;
  v:array[0..7000] of boolean;
  i,j,k,l:longint;
  n,m:longint;

function min(x,y:longint):longint;
begin
  if x<y
    then exit(x)
    else exit(y);
end;

procedure dfs(r:longint);
var
  i,j,k:longint;
  c,t,ii:longint;
begin
  v[r]:=false;
  if a[r,0]=0
    then
      begin
        f[r,0]:=w[r];
        f[r,1]:=0;
        f[r,2]:=w[r];
        exit;
      end;
  for i:=1 to a[r,0] do
    if v[a[r,i]] then dfs(a[r,i]);
  t:=0;
  for i:=1 to a[r,0] do
    begin
      c:=a[r,i];
      t:=t+min(f[c,0],f[c,2]);
    end;
  f[r,2]:=maxlongint;
  ii:=t;
  for i:=1 to a[r,0] do
    begin
      c:=a[r,i];
      f[r,0]:=f[r,0]+min(min(f[c,0],f[c,1]),f[c,2]);
      f[r,1]:=f[r,1]+min(f[c,0],f[c,2]);
      t:=t-min(f[c,0],f[c,2])+f[c,0];
      f[r,2]:=min(f[r,2],t);
      t:=ii;
    end;
  f[r,0]:=f[r,0]+w[r];
end;

begin
  readln(n);
  fillchar(v,sizeof(v),1);
  for i:=1 to n do
    begin
      read(j,w[j],a[j,0]);
      for k:=1 to a[j,0] do
        begin
          read(l);
          a[j,k]:=l;
          v[l]:=false;
        end;
      readln
    end;
  for i:=1 to n do
    if v[i] then break;
  fillchar(v,sizeof(v),1);
  dfs(i);
  write(min(f[i,0],f[i,2]));
end.

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