bzoj 1596 电话网络

Description

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计算一下,为了建立能
覆盖到所有草地的通信系统,他最少要建多少座无线电通讯塔。

Input

* 第1行: 1个整数,N
* 第2..N行: 每行为2个用空格隔开的整数A、B,为两块相邻草地的编号

Output

* 第1行: 输出1个整数,即FJ最少建立无线电通讯塔的数目

Sample Input

5
1 3
5 2
4 3
3 5
输入说明:
Farmer John的农场中有5块草地:草地1和草地3相邻,草地5和草地2、草地
4和草地3,草地3和草地5也是如此。更形象一些,草地间的位置关系大体如下:
(或是其他类似的形状)
4 2
| |
1--3--5

Sample Output

2
输出说明:
FJ可以选择在草地2和草地3,或是草地3和草地5上建通讯塔。
 
思路:本题为动态规划,dp[i][0]表示以i为根的子树最少需要放几个,同时i的父亲没有放。
dp[i][1]表示以i为根的子树最少需要放几个,同时i父亲没有放,但是已经被关联。
dp[i][2]表示以i为根的字数最少需要放几个,并且i的父亲已经放了。
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define R  register int
 4 #define rep(i,a,b) for(R i=a;i<=b;i++)
 5 #define Rep(i,a,b) for(R i=a;i>=b;i--)
 6 #define rp(i,x)    for(R i=H[x];i!=-1;i=E[i].nt)
 7 #define ms(i,a)    memset(a,i,sizeof(a))
 8 template<class T>void read(T &x){
 9   x=0; char c=0;
10   while (!isdigit(c)) c=getchar();
11   while (isdigit(c)) x=x*10+(c^48),c=getchar();
12 }
13 int const N=10000+3;
14 int const inf=1e8;
15 struct Edge{
16   int to,nt;
17 }E[N<<1];
18 int n,cnt,dp[N][3],H[N];
19 void add(int a,int b){
20   E[cnt]=(Edge){b,H[a]}; H[a]=cnt++;
21 }
22 void dfs(int x,int fa){
23   int s1=0,s2=0;
24   rp(i,x){
25     int v=E[i].to;
26     if(v==fa) continue;
27     dfs(v,x);
28     s1+=dp[v][1];
29     s2+=dp[v][2];
30   }
31   dp[x][0]=1+s2;
32   dp[x][1]=1+s2;
33   rp(i,x){
34     int v=E[i].to;
35     if(v==fa) continue;
36     dp[x][1]=min(dp[x][1],s1-dp[v][1]+dp[v][0]);
37   }
38   dp[x][2]=min(1+s2,s1);
39 }
40 int main(){
41   read(n);
42   ms(-1,H);
43   rep(i,1,n-1){
44     int x,y; read(x);read(y); add(x,y); add(y,x);
45   }
46   dfs(1,1);
47   printf("%d\n",dp[1][1]);
48   return 0;
49 }
View Code

 

 
posted @ 2019-01-02 14:34  zjxxcn  阅读(213)  评论(0编辑  收藏  举报