bzoj 1596: [Usaco2008 Jan]电话网络
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
查错查了半天。。。。
直接讲题解吧,还是比较裸的树形DP
f[x][0]表示这个点不选
f[x][1]表示这个选
f[x][2]表示这个点不会选但是至少会选一个儿子
转移看代码吧。。
#include<stdio.h> #include<iostream> using namespace std; const int N=10005; int n,i,x,y,f[N][3]; int tot,head[N],Next[N<<1],to[N<<1]; void add(int x,int y) { tot++; to[tot]=y; Next[tot]=head[x]; head[x]=tot; } void dfs(int x,int pre) { f[x][0]=0; f[x][1]=1; f[x][2]=1000000; int i,y,s=0; for(i=head[x];i!=-1;i=Next[i]) if(to[i]!=pre) dfs(to[i],x); for(i=head[x];i!=-1;i=Next[i]) { y=to[i]; if(y==pre) continue; f[x][1]+=min(f[y][2],min(f[y][1],f[y][0])); f[x][0]+=min(f[y][2],f[y][1]); s+=min(f[y][2],f[y][1]); } for(i=head[x];i!=-1;i=Next[i]) { y=to[i]; if(y==pre) continue; f[x][2]=min(f[x][2],f[y][1]+s-min(f[y][2],f[y][1])); } } int main() { scanf("%d",&n); for(i=1;i<=n;i++) head[i]=-1; for(i=1;i<n;i++) { scanf("%d%d",&x,&y); add(x,y); add(y,x); } dfs(1,0); cout<<min(f[1][2],f[1][1]); return 0; }
一念起,天涯咫尺; 一念灭,咫尺天涯。