1596: [Usaco2008 Jan]电话网络

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上建通讯塔。

HINT

 

Source

Gold

 

黄学长的题解:

  f[i][0]:以i为根的子树中所有点均被覆盖且草地i上无信号塔所需的最小塔数(i被其儿子覆盖)

  f[i][1]:以i为根的子树中所有点均被覆盖且草地i上有信号塔所需的最小塔数

  f[i][2]:以i为根的子树中除i点以外其余点均被覆盖所需的最小塔数

1 很容易想到是树形DP,然后对于一个节点i,如果在它的上面建立无线电发射塔的话,那么只需要考虑在他的儿子里面取min即可;
2 然后自然而然的想到要转移i节点没有建立发射塔的情况,那么一种情况是它被它的儿子覆盖,另一种是被他的父亲覆盖,
3 对于被他的父亲覆盖这种情况,只需要对它的儿子没有建立发射塔并被覆盖的情况求和即可,
4 对于被他的儿子覆盖这种情况,可以枚举他被某个儿子覆盖,其他的儿子随便取,这样就好了。
个人理解
 1 #include<iostream>
 2 #include<cstdlib>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<algorithm>
 7 #include<string>
 8 #include<map>
 9 #include<queue>
10 #include<vector>
11 #include<set>
12 #define inf 100000000
13 #define maxn 10005
14 #define maxm 10000+5
15 #define eps 1e-10
16 #define ll long long
17 #define for0(i,n) for(int i=0;i<=(n);i++)
18 #define for1(i,n) for(int i=1;i<=(n);i++)
19 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
20 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
21 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go)
22 using namespace std;
23 int tot,head[maxn],f[3][maxn];
24 struct edge{
25     int go,next;
26 }e[maxn*2];
27 int read(){
28     int x=0,f=1;char ch=getchar();
29     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
30     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
31     return x*f;
32 }
33 void insert(int u,int v){
34     e[++tot].go=v;e[tot].next=head[u];head[u]=tot;
35 }
36 void dp(int x,int fa){
37     int sum=0;
38     f[1][x]=1;f[0][x]=inf;
39     for(int i=head[x];i;i=e[i].next){
40         int y=e[i].go;
41         if(y==fa)continue;
42         dp(y,x);
43         f[1][x]+=min(f[0][y],min(f[1][y],f[2][y]));
44         f[2][x]+=f[0][y];
45         sum+=min(f[0][y],f[1][y]);
46     }
47     for(int i=head[x];i;i=e[i].next){
48         int y=e[i].go;
49         if(y==fa)continue;
50         f[0][x]=min(f[0][x],f[1][y]+sum-min(f[0][y],f[1][y]));
51     }
52 } 
53 int main(){
54     //freopen("input.txt","r",stdin);
55     //freopen("output.txt","w",stdout);
56     int n=read();
57     for1(i,n-1){
58         int u=read(),v=read();
59         insert(u,v);insert(v,u);
60     }
61     dp(1,0);
62     printf("%d",min(f[0][1],f[1][1]));
63     return 0;
64 }
View Code

 

 

by:也可以用贪心来做。。。。。。

posted @ 2016-03-19 15:37  HTWX  阅读(128)  评论(0编辑  收藏  举报