Farmer John决定为他的所有奶牛都配备手机,以此鼓励她们互相交流。不过,为此FJ必须在奶牛们居住的N(1 <=
N <= 10,000)块草地中选一些建上无线电通讯塔,来保证任意两块草地间都存在手机信号。所有的N块草地按1..N
顺次编号。 所有草地中只有N-1对是相邻的,不过对任意两块草地A和B(1 <= A <= N; 1 <= B <= N; A != B),都
可以找到一个以A开头以B结尾的草地序列,并且序列中相邻的编号所代表的草地相邻。无线电通讯塔只能建在草地
上,一座塔的服务范围为它所在的那块草地,以及与那块草地相邻的所有草地。 请你帮FJ计算一下,为了建立能
覆盖到所有草地的通信系统,他最少要建多少座无线电通讯塔。
* 第1行: 1个整数,N
* 第2..N行: 每行为2个用空格隔开的整数A、B,为两块相邻草地的编号
* 第1行: 输出1个整数,即FJ最少建立无线电通讯塔的数目
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#define N 10010
#define E 20020
using namespace std;
int n,cnt;
int head[N],dp[N][3];
struct edge{
int r,next;
}e[E];
void insert(int u,int v){
e[++cnt].r=v;
e[cnt].next=head[u];
head[u]=cnt;
}
void tree_DP(int x,int F){
int sum=0;
dp[x][1]=1;dp[x][0]=N;
for(int i=head[x];i>0;i=e[i].next)
if(e[i].r!=F){
tree_DP(e[i].r,x);
dp[x][1]+=min(dp[e[i].r][0],min(dp[e[i].r][1],dp[e[i].r][2]));
dp[x][2]+=dp[e[i].r][0];
sum+=min(dp[e[i].r][0],dp[e[i].r][1]);
}
for(int i=head[x];i>0;i=e[i].next)
if(e[i].r!=F)
dp[x][0]=min(dp[x][0],dp[e[i].r][1]+sum-min(dp[e[i].r][0],dp[e[i].r][1]));
}
int main(){
int x,y,ans;
cnt=0;
scanf("%d",&n);
for(int i=1;i<n;i++){
scanf("%d%d",&x,&y);
insert(x,y);
insert(y,x);
}
tree_DP(1,0);
ans=min(dp[1][0],dp[1][1]);
printf("%d\n",ans);
return 0;
}
This passage is made by Iscream-2001.