消防局的设立

P2279 [HNOI2003]消防局的设立

主要思路:贪心,从叶子节点开始(按深度排序即可做到),从它父亲的父亲,把距离不超过 \(2\) 的节点都打上标记,\(ans++\)。这样一定最优,因为必须覆盖那个没被覆盖的节点,而从祖父开始可以覆盖更多的点。注意把根节点的父亲设为根节点,否则从根节点开始跳就RE了

#include<bits/stdc++.h>
using namespace std;
const int N=1005;
int n,ans;
bool vis[N];
vector<int>g[N];
int p[N];
struct node2{
    int depth,id;
}d[N];
bool cmp(node2 a,node2 b)
{
    return a.depth>b.depth;
}
void dfs1(int now,int deep,int fa)
{
    d[now].depth=deep;
    p[now]=fa;
    for(int i=0;i<g[now].size();i++)
    {
        if(g[now][i]==fa) continue;
        dfs1(g[now][i],deep+1,now);
    }
}
void era(int now,int dis,int fa)
{
    if(dis>2)return;
    vis[now]=true;
    for(int i=0;i<g[now].size();i++)
    {
        if(g[now][i]!=fa)era(g[now][i],dis+1,now);
    }
}
int main()
{
    scanf("%d",&n);
    p[1]=1;
    d[1].id=1;
    d[1].depth=1;
    for(int i=2;i<=n;i++)
    {
        int x;
        scanf("%d",&x);
        d[i].id=i;
        g[x].push_back(i);
        g[i].push_back(x);
    }
    dfs1(1,1,1);
    sort(d+1,d+n+1,cmp);
    for(int i=1;i<=n;i++)
    {
        if(vis[d[i].id])continue;
        int grand=p[p[d[i].id]];
        era(grand,0,grand);
        ans++;
    }
    printf("%d\n",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/zzctommy/p/12316980.html