[BZOJ1217][HNOI2003]消防局的设立(贪心)

[BZOJ1217]

这题也有树规的打法,但好复杂啊

贪心是这样的,对于深度最深的一个叶子节点,要覆盖它的话,肯定是覆盖它的爷爷是最优的

这样它的父亲跟兄弟都会被覆盖

所以每次找深度最深的,覆盖它的爷爷就行了

Code

 

#include <cstdio>
#include <algorithm>
#include <queue>
#include <vector>
#define N 1010
using namespace std;

int n,head[N],tot,dep[N],fa[N],Ans;
struct info{int to,nex;}e[N*2];
struct cmp{bool operator() (int a,int b){return dep[a]<dep[b];}};
priority_queue<int,vector<int>,cmp> q;
bool vis[N];

inline void Link(int u,int v){
	e[++tot].to=v;e[tot].nex=head[u];head[u]=tot;
}

inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

void dfs(int u,int fa){
	for(int i=head[u];i;i=e[i].nex){
		int v=e[i].to;
		if(v==fa) continue;
		dep[v]=dep[u]+1;
		::fa[v]=u;
		dfs(v,u);
	}
}

void dddfs(int u,int dp){
	if(dp>2) return;
	vis[u]=1;
	for(int i=head[u];i;i=e[i].nex) dddfs(e[i].to,dp+1);
}

int main(){
	n=read();
	for(int i=2;i<=n;++i){
		int v=read();
		Link(i,v),Link(v,i);
	}
	dfs(1,0);
	for(int i=1;i<=n;++i) q.push(i);
	while(!q.empty()){
		while(!q.empty()&&vis[q.top()]) q.pop();
		if(q.empty()) break;
		dddfs(fa[fa[q.top()]]?fa[fa[q.top()]]:1,0);
		++Ans;
	}
	printf("%d\n",Ans);
	return 0;
}

 

posted @ 2018-05-10 19:09  void_f  阅读(116)  评论(0编辑  收藏  举报