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