[HNOI2003]消防局的设立【贪心水题】

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

显然的一个贪心就是每次选择最深的没有覆盖的点的父亲的父亲作为消防局,然后暴力覆盖一下: O ( n 2 ) O(n^2)

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define ll long long
#define rep(i,x,y) for(ll i=(x);i<=(y);i++)
#define repl(i,x,y) for(ll i=(x);i<(y);i++)
#define repd(i,x,y) for(ll i=(x);i>=(y);i--)
using namespace std;
 
const ll N=1e3+5;
const ll Inf=1e18; 

ll n,num,fa[N],vis[N],dep[N];
ll cnt,to[N],nxt[N],head[N];
 
inline ll read() {
    ll x=0;char ch=getchar();bool f=0;
    while(ch>'9'||ch<'0'){if(ch=='-')f=1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    return f?-x:x;
}

void ins(ll x,ll y) {
	to[++cnt]=y;nxt[cnt]=head[x];head[x]=cnt;
}

void dfs(ll x,ll d) {
	vis[x]=1;
	
	if(d==0) return ;
	
	for(ll i=head[x];i;i=nxt[i]) dfs(to[i],d-1);dfs(fa[x],d-1);
} 

int main() {
	n=read();
	
	rep(y,2,n) {
		ll x=read();
		ins(x,y);fa[y]=x;
	}
	
	fa[1]=1;rep(i,1,n) dep[i]=dep[fa[i]]+1;
	
	while(true) {
		ll pos=0;
		rep(i,1,n) if(!vis[i]&&dep[i]>dep[pos]) pos=i;
		
		if(pos==0) break;
		
		dfs(fa[fa[pos]],2);++num;
	}
	
	printf("%lld\n",num);
	
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/yanzhenhuai/article/details/82960072
今日推荐