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
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上建通讯塔。
输出说明:
FJ可以选择在草地2和草地3,或是草地3和草地5上建通讯塔。
HINT
Source
黄学长的题解:
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 }
by:也可以用贪心来做。。。。。。