[Usaco2008 Jan]电话网络
[Usaco2008 Jan]电话网络
描述
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最少建立无线电通讯塔的数目
样例
输入
5 1 3 5 2 4 3 3 5 输入说明: Farmer John的农场中有5块草地:草地1和草地3相邻,草地5和草地2、草地 4和草地3,草地3和草地5也是如此。更形象一些,草地间的位置关系大体如下: (或是其他类似的形状)
输出
2 输出说明: FJ可以选择在草地2和草地3,或是草地3和草地5上建通讯塔
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,head[1000001],tot,f[10001][3]; 4 //f[i][0] i被自己覆盖 5 //f[i][1] i被儿子覆盖 6 //f[i][2] i被父亲覆盖 7 //f[i][0]+=min(f[son][1],f[son][2],f[son][0]) 8 //f[i][1]=f[x][0]+sigma(min (f[son][0],f[son][1]) ) 9 //f[i][2]+=min(f[son][0],f[son][1]) 10 struct data { 11 int to,nxt; 12 } e[1000001]; 13 void add(int x,int y) { 14 e[++tot].to=y; 15 e[tot].nxt=head[x]; 16 head[x]=tot; 17 } 18 void dp(int x,int fa) { 19 int special_son=0; 20 f[x][0]=1; 21 for(int i=head[x]; i; i=e[i].nxt) { 22 int v=e[i].to; 23 if(v==fa) 24 continue; 25 dp(v,x); 26 f[x][2]+=min(f[v][0],f[v][1]); 27 f[x][0]+=min(min(f[v][0],f[v][1]),f[v][2]); 28 if(f[special_son][0]-min(f[special_son][0],f[special_son][1])>f[v][0]-min(f[v][1],f[v][0])) 29 special_son=v; 30 } 31 f[x][1]=f[special_son][0]; 32 for(int i=head[x];i;i=e[i].nxt){ 33 int v=e[i].to; 34 if(v==fa||v==special_son) 35 continue; 36 f[x][1]+=min(f[v][1],f[v][0]); 37 } 38 } 39 int main() { 40 scanf("%d",&n); 41 for(int i=1,x,y; i<n; i++) { 42 scanf("%d%d",&x,&y); 43 add(x,y); 44 add(y,x); 45 } 46 f[0][0]=0x3f; 47 dp(1,-1); 48 printf("%d\n",f[1][1]<f[1][0]?f[1][1]:f[1][0]); 49 return 0; 50 }