Dili_iiii

编码全要靠底力

k半径覆盖问题

题意

一个点可以覆盖半径2以内的的点,最少多少点可以全覆盖(可以延伸为k半径)

 

预处理出每个点深度,从最深的点开始网上覆盖,dis数组表示最近的覆盖中心点的距离,大于2(k)时,把他的2(k)代设成覆盖中心(贪心思想,保证最远且刚好能覆盖当前点)

 

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int maxn=500005;
int n;
int dis[100005],fa[100005],dep[100005],id[100005],ant;
bool cmp(int a,int b)
{
    return dep[a]>dep[b];
}
int main()
{
    scanf("%d",&n);
    id[1]=1;
    dis[0]=dis[1]=maxn;
    for(int i=2;i<=n;i++)
    {
        scanf("%d",&fa[i]);
        dep[i]=dep[fa[i]]+1;
        id[i]=i;
        dis[i]=maxn;
    }
    sort(id+1,id+1+n,cmp);
    for(int i=1;i<=n;i++)
    {
        int now=id[i];
        int f=fa[now];
        int gf=fa[fa[now]];
        dis[now]=min(dis[now],dis[f]+1);
        dis[now]=min(dis[now],dis[gf]+2);
        if(dis[now]>2)
        {
            ant++;
            dis[gf]=0;
            dis[fa[gf]]=min(dis[fa[gf]],1);
            dis[fa[fa[gf]]]=min(dis[fa[fa[gf]]],2);
        }
    }
    printf("%d\n",ant);
    return 0;
}

 

posted @ 2019-07-21 20:20  Dili_iiii  阅读(223)  评论(0编辑  收藏  举报