【题解】洛谷P2279 消防局的设立(dfs/贪心)

这道题虽然在洛谷上归类为动态规划(树形dp),然而思考后我们可以用贪心来解决这个问题。

由于我们得到的是一个树形结构,所以我们可以模拟出这么一棵树来,然后通过dfs求出树每一个叶子结点的深度(根节点深度最小为1)。注意用dfs求深度要记录下结点的父亲结点,后面有用。因为消防局可以扑灭和它所在城市距离为2的城市的火灾,所以我们贪心,将求出的最深的节点找到,然后通过fa数组寻找其爷爷结点,并将其标记下来。接着,我们利用search函数来把和该节点距离为2的所有节点都打上标记。然后再重复这个过程,直到所有的结点都被标记过为止。注意需要利用前向星链状结构存图。里面的head[x]指的是x与其他子节点连边的tot,nnext[i]指的是将这个tot跳到另一个tot上去,to[i]就是to的tot那条边得到和x相连的结点。最后为了防止只剩下1结点没有被染色,我们应当让depth[i]>=depth[pd]。还要处理有爷爷结点和没有爷爷节点的情况。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iomanip>
using namespace std;
const int maxn=1000+5;
int n;
int depth[maxn],head[maxn],to[maxn*2],nnext[maxn*2],fa[maxn];
int b[maxn],team[maxn];
int tot;
int s=0,t=0;
int ans=0;
void add(int x,int y)
{
	tot++;
	nnext[tot]=head[x];
	head[x]=tot;
	to[tot]=y;
}
void search(int x)
{
	for(int i=head[x];i;i=nnext[i])
	{
		int now=to[i];
		b[now]=true;
		for(int j=head[now];j;j=nnext[j])
		{
			b[to[j]]=true;
		}
	}
}
void dfs(int x)
{
	for(int i=head[x];i;i=nnext[i])
	{
		int y=to[i];
		if(y==fa[x]) continue;
		fa[y]=x;
		depth[y]=depth[x]+1;
		dfs(y);
	}
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n-1;i++)
	{
		int q;
		cin>>q;
		add(i+1,q);
		add(q,i+1);
	}
	depth[1]=1;
	dfs(1);
/*	team[t]=1;
	t++;
	b[1]=true;*/
	
/*	while(s!=t)
	{
		int now=team[s];
		s++;
		for(int i=head[now];i;i=nnext[i])
		{
			int x=to[i];
			if(b[x]==false)
			{
				fa[x]=now;
				depth[x]=depth[now]+1;
				b[x]=true;
				team[t]=x;
				t++;
			}
		}
	}*/
//	int pd=1;
//	memset(b,false,sizeof(b));
	while(true)
	{
		bool ok=false;
		int pd=1;
		for(int i=1;i<=n;i++)
		{
			if(depth[i]>=depth[pd]&&b[i]==false)
			{
				pd=i;
				ok=true;
			}
		}
		if(ok==false)
		{
			break;
		}
		if(fa[fa[pd]]!=0)
		{
			search(fa[fa[pd]]);
		}
		else if(fa[pd]!=0)
		{
			search(fa[pd]);
		}
		else search(pd);
		ans++;
	}
	/*
	memset(b,false,sizeof(b));
	for(int j=1;j<=n;j++)
	{
		if(depth[j]>md&&b[j]==false)
		{
			md=depth[j];
			pd=j;
			for(int i=1;i<=n;i++)
			{
				if(depth[i]==depth[pd]-2&&fa[fa[pd]]==i&&b[i]==false)
				{
					ans++;
					b[i]=true;
					b[pd]=true;
					search(i);
					break;
				}
			}	
		}
	}*/
	printf("%d",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/rem_inory/article/details/81038256