1217: [HNOI2003]消防局的设立
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 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
1
2
3
4
5
Sample Output
2
HINT
Source
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);
}