【洛谷P2279】[HNOI2003]消防局的设立

消防局的设立

题目链接

贪心:每次取出深度最大的节点,若没有被覆盖到,要想覆盖它,

最优的做法显然是将它的爷爷设为消防局

(因为该节点深度为最大,选兄弟、父亲所覆盖的节点,选了爷爷后都能够覆盖)

用优先队列维护深度即可

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
#define INF 100000
#define N 1010
int n,Head[N],num,ans,fa[N];
int ok[N],deep[N],vis[N];
struct cmp{
    bool operator ()(int a,int b){
        return deep[a]<deep[b];
    }
};
struct NODE{
    int to,next;
} e[N<<1];
priority_queue< int, vector<int>, cmp > q;
inline int read(){
    int x=0; char c=getchar();
    while(c<'0'||c>'9') c=getchar();
    while('0'<=c&&c<='9') { x=(x<<3)+(x<<1)+c-'0'; c=getchar(); }
    return x;
}
inline void add(int x,int y){
    e[++num].to=y;
    e[num].next=Head[x];
    Head[x]=num;
}
void dfs(int t,int f){
    fa[t]=f;
    deep[t]=deep[f]+1;
    for(int i=Head[t];i;i=e[i].next)
     if(e[i].to!=f) dfs(e[i].to,t);
}
void dfs2(int t,int dep){
    if(dep==2) return;
    for(int i=Head[t];i;i=e[i].next){
        int v=e[i].to;
        vis[v]=1;
        dfs2(v,dep+1);
    }
}
int main()
{
    n=read(); int x;
    for(int i=2;i<=n;i++){
        x=read();
        add(i,x); add(x,i);
    }
    dfs(1,-1);
    for(int i=1;i<=n;i++) q.push(i);
    int u,gf;
    while(!q.empty()){
        u=q.top(); q.pop();
        if(vis[u]) continue;
        ans++;
        if(fa[u]!=-1)
         if(fa[fa[u]]!=-1)
          gf=fa[fa[u]];
            else gf=fa[u];
           else gf=u;
           vis[gf]=1;
           dfs2(gf,0);
    }
    printf("%d\n",ans);
    return 0;
}

 

posted @ 2018-08-03 18:58  yjk  阅读(105)  评论(0编辑  收藏  举报