bzoj1596 电话网络

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
 
虽然看起来是树dp,但是明明可以贪心。但是由于我dp太烂,还是打dp吧。
然后在4ms的时候wa了,看了很久没有看出bug来,最后发现是INF设的太大,加爆掉了变成负数一取min就完了
说明取INF不是越大越好啊
//Serene
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int maxn=1e4+10,INF=maxn;//
int n,ans[3][maxn];
//ans[i][0]:以i为根的子树中所有点均被覆盖且草地i上无信号塔所需的最小塔数(i被其儿子覆盖)
//ans[i][1]:以i为根的子树中所有点均被覆盖且草地i上有信号塔所需的最小塔数
//ans[i][2]:以i为根的子树中除i点以外其余点均被覆盖所需的最小塔数

int aa;char cc;
int read() {
	aa=0;cc=getchar();
	while(cc<'0'||cc>'9') cc=getchar();
	while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
	return aa;
}

int fir[maxn],nxt[2*maxn],to[2*maxn],e=0;
void add(int x,int y) {
	to[++e]=y;nxt[e]=fir[x];fir[x]=e;
	to[++e]=x;nxt[e]=fir[y];fir[y]=e;
}

int fa[maxn];
void dfs(int pos) {
	ans[0][pos]=INF;ans[1][pos]=1;
	int xx,sum=0,z;//
	for(int y=fir[pos];y;y=nxt[y]) {
		z=to[y]; if(z==fa[pos]) continue;
		fa[z]=pos; dfs(z);
		xx=min(ans[0][z],ans[1][z]); sum+=xx;
		ans[1][pos]+=min(xx,ans[2][z]); ans[2][pos]+=ans[0][z];
		ans[0][pos]=min(ans[0][pos],ans[1][z]-xx);
	}
	ans[0][pos]+=sum; 
}

int main() {
	n=read(); int x,y;
	for(int i=1;i<n;++i) {
		x=read();y=read();
		add(x,y);
	}
	dfs(1);
	printf("%d",min(ans[0][1],ans[1][1]));
	return 0;
}

  

posted @ 2017-09-08 09:21  shixinyi  阅读(180)  评论(0编辑  收藏  举报