[BZOJ1596] [Usaco2008 Jan]电话网络

传送门

http://www.lydsy.com/JudgeOnline/problem.php?id=1596

题目大意

给定一棵树,每个点可以放置一个物品覆盖这个点直接连接的点,询问最少物品数

题解

树形DP
dp[i,1] :i放物品,使i和i的子树中节点都被覆盖的最小物品数
dp[i,2] :i不放物品,使i和i的子树中节点都被覆盖的最小物品数
dp[i,3] :i不放物品,i不被覆盖,i的子树中节点都被覆盖的最小物品数
dp[i,1]=1+min(dp[son[i],1],dp[son[i],2],dp[son[i],3])
dp[i,3]=dp[son[i],2]
dp[i,2]=min(dp[son[i],1],dp[son[i],2])+dp[son[i],1]min(dp[son[i],1],dp[son[i],2])

var
 dp:array[0..10005,1..3]of longint;
 x,y:array[0..10005]of longint;
 w:array[0..20005,1..2]of longint;
 i,j,k:longint;
 a,b,c:longint;
 n,m,len:longint;
procedure init(a,b:longint);
begin
 w[len,1]:=b;
 if w[a,2]=0
 then w[a,2]:=len else w[w[a,1],2]:=len;
 w[a,1]:=len; inc(len);
end;

function min(a,b:longint):longint;
begin
 if a<b then exit(a) else exit(b);
end;

procedure dfs(a:longint);
var tt,s:longint;
begin
 x[a]:=1; tt:=w[a,2]; dp[a,1]:=1; dp[a,2]:=0; dp[a,3]:=0; s:=n;
 while tt<>0 do
  begin
   if x[w[tt,1]]=0 then begin
    dfs(w[tt,1]);
    dp[a,1]:=dp[a,1]+min(min(dp[w[tt,1],1],dp[w[tt,1],2]),dp[w[tt,1],3]);
    dp[a,2]:=dp[a,2]+min(dp[w[tt,1],1],dp[w[tt,1],2]);
    s:=min(s,dp[w[tt,1],1]-min(dp[w[tt,1],1],dp[w[tt,1],2]));
    dp[a,3]:=dp[a,3]+dp[w[tt,1],2];
   end;
   tt:=w[tt,2];
  end;
 dp[a,2]:=dp[a,2]+s;
end;

begin
 readln(n); len:=n+1;
 for i:=1 to n-1 do
  begin
   readln(a,b);
   init(a,b); init(b,a);
  end;
 dfs(1);
 writeln(min(dp[1,1],dp[1,2]));
end.

你可能感兴趣的:([BZOJ1596] [Usaco2008 Jan]电话网络)