题意:有一棵树,若在某个节点上放一个士兵则与该节点相连的边都会被看到。问最少放多少个士兵可以看到所有的边。
分析:很明显的树形dp。f[i]表示节点i放士兵且以i为根的树的边全被看到最少放的士兵数。g[i]表示节点i不放士兵且以i为根的树的边全被看到最少放的士兵数。
f[i]=sum(min(f[soni],g[soni]))+1
g[i]=sum(f[soni])
真是不爽一开始看错题目把边看成了点,弄得我调了好久,差点还以为数据和标程都是错的。
看来看清楚题目真的很重要啊!!!
代码:
var n,x,y,z,i,j,root:longint; f,g,d:array[0..1500] of longint; a:array[0..1500,0..1500] of longint; function min(x,y:longint):longint; begin if x<y then exit(x) else exit(y); end; procedure dp(x:longint); var i:longint; begin for i:=1 to a[x,0] do dp(a[x,i]); f[x]:=1; g[x]:=0; for i:=1 to a[x,0] do begin f[x]:=f[x]+min(f[a[x,i]],g[a[x,i]]); g[x]:=g[x]+f[a[x,i]]; end; end; begin readln(n); for i:=1 to n do begin read(x,y); for j:=1 to y do begin read(z); inc(a[x,0]); a[x,a[x,0]]:=z; inc(d[z]); end; readln; end; for i:=0 to n-1 do if d[i]=0 then begin root:=i; break; end; dp(root); writeln(min(f[root],g[root])); end.