【刷题】【贪心】【树】消防局的设立

一棵树,n个基地

每个消防局有能力扑灭与它距离不超过2的基地的火灾。

你的任务是计算至少要修建多少个消防局才能够确保火星上所有的基地在发生火灾时,消防队有能力及时扑灭火灾。、

(luogu)

这题贪心比较好想

考虑当前深度最大的叶子结点,你肯定要有一个消防局去覆盖它,

那么既然他是叶子结点,所以与他距离小于等于2的节点有这么几种:

  1. 他的父亲 2. 他的兄弟 3. 他的爷爷

容易看出,在前两项能够覆盖到的节点,在爷爷那里设立一定也能覆盖到。

所以每次贪心取出深度最大的节点,在他的爷爷哪里放一个消防站

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<queue>
using namespace std;
int n;
const int N=1003;
int fa[N],dep[N],xl[N];
bool cmp(int a,int b)
{ return dep[a]<dep[b]; }

int tot,head[N];
int ev[N<<1],enx[N<<1];
void add(int u,int v)
{ ev[++tot]=v,enx[tot]=head[u],head[u]=tot; }

bool hav[N];
int ans;
void dfs(int st,int pre,int ll)
{
    hav[st]=true;
    if(ll==2 ) return ;
    
    for(int i=head[st];i;i=enx[i])
        if(ev[i]!=pre )
            dfs(ev[i],st,ll+1);
}

int main()
{
    scanf("%d",&n);
    int x;
    for(int i=2;i<=n;i++)
        scanf("%d",&x),fa[i]=x,add(x,i),add(i,x);
    for(int i=1;i<=n;i++)
        dep[i]=dep[fa[i]]+1,xl[i]=i;
    sort(xl+1,xl+n+1,cmp);
    
    for(int i=n;i;i--)
    {
        if(hav[xl[i]]) continue;
        
        int v=xl[i];
        if(fa[v]) v=fa[v];
        if(fa[v]) v=fa[v];
        ans++;
        
        dfs(v,0,0);
    }
    printf("%d
",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/xwww666666/p/11721693.html