BZOJ 1217: [HNOI2003]消防局的设立

1217: [HNOI2003]消防局的设立

Time Limit: 10 Sec   Memory Limit: 162 MB
Submit: 741   Solved: 410
[ Submit][ Status][ Discuss]

Description

2020年,人类在火星上建立了一个庞大的基地群,总共有n个基地。起初为了节约材料,人类只修建了n-1条道路来连接这些基地,并且每两个基地都能够通过道路到达,所以所有的基地形成了一个巨大的树状结构。如果基地A到基地B至少要经过d条道路的话,我们称基地A到基地B的距离为d。由于火星上非常干燥,经常引发火灾,人类决定在火星上修建若干个消防局。消防局只能修建在基地里,每个消防局有能力扑灭与它距离不超过2的基地的火灾。你的任务是计算至少要修建多少个消防局才能够确保火星上所有的基地在发生火灾时,消防队有能力及时扑灭火灾。

Input

输入文件的第一行为n,表示火星上基地的数目。接下来的n-1行每行有一个正整数,其中文件第i行的正整数为a[i],表示从编号为i的基地到编号为a[i]的基地之间有一条道路,为了更加简洁的描述树状结构的基地群,有a[i]

Output

输出文件仅有一个正整数,表示至少要设立多少个消防局才有能力及时扑灭任何基地发生的火灾。

Sample Input

6
1
2
3
4
5

Sample Output

2

HINT

Source

[ Submit][ Status][ Discuss]

HOME   Back

简单的贪心。搞不懂为啥很多人要写DP。

贪心的思想就是尽量在父亲建消防站。

看看代码就知道了。

BZOJ传送门:点击打开链接

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int head[10001],nxt[20001],point[20001];
int n,vi,tot,ans;
bool cover[10001],Must[10001];
void addedge(int x,int y){
	tot++;nxt[tot]=head[x];head[x]=tot;point[tot]=y;
	tot++;nxt[tot]=head[y];head[y]=tot;point[tot]=x;
}
int dfs(int now,int father){
	int farson=0;
	for(int tmp=head[now];tmp;tmp=nxt[tmp]){
		int v=point[tmp];
		if(v!=father){
			int x=dfs(v,now);
			if(!cover[x])
				farson=max(farson,x+1);
		}
	}
	if(Must[now]){
		cover[father]=true;
		cover[now]=true;
		return -1;	
	}
	bool hehe=false;
	for(int tmp=head[now];tmp;tmp=nxt[tmp]){
		int v=point[tmp];
		if(v!=father){
			if(Must[v]){
				hehe=true;
				break;
			}
		}
	}
	if(hehe){
		cover[father]=true;
		cover[now]=true;
		return -1;
	}
	if(farson==0) {
		if(now==1&&!cover[now])Must[0]=true;
		if(cover[now]) return -1;
		else  return 0;
	}
	else{
		Must[father]=true;
		return 1;
	}
		
}
int main(){
	scanf("%d",&n);
	for(int i=2;i<=n;i++){
		scanf("%d",&vi);
		addedge(i,vi);
	}	
	dfs(1,0);
	for(int i=0;i<=n;i++)if(Must[i])ans++;
	printf("%d\n",ans);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值