[HNOI2003] 消防局的设立

传送门:>HERE<

题意:给出一颗树,先要求在一些点上设立消防局。每个消防局能够覆盖与它距离不大于2的其他点。求最少设置几个消防局才能够覆盖所有节点。

解题思路:

  贪心:每次选取还没有被覆盖的深度最大的点,在它的爷爷那里设立消防局。

  为什么这样是正确的呢?这里有一个很巧妙的思路:由于我目前选择的是没有标记的并且是最深的了,所以肯定不存在还没有标记的但比这个点更深的点了(已经被覆盖的点我们肯定不会去浪费机会再设立了)。因此想要覆盖当前这个最深的点,有三个选择:1.设立在它父亲 2.设立在它兄弟 3.设立在它爷爷

  很容易发现,如果设立在了它爷爷那里,一定覆盖了它父亲和它兄弟,因此我们就可以贪心地选择在它爷爷那里设立

Code

  细节。不知道为什么在洛谷AC了,在BZOJ却CE了

/*by DennyQi*/
#include <cstdio>
#include <queue>
#include <algorithm>
#include <cstring>
#define  r  read()
#define  Max(a,b)  (((a)>(b))?(a):(b))
#define  Min(a,b)  (((a)<(b))?(a):(b))
using namespace std;
const int MAXN = 1010;
const int INF = 0x3f3f3f3f;
inline int read(){
    int x = 0; int w = 1; register char c = getchar();
    while(c ^ '-' && (c < '0' || c > '9')) c = getchar();
    if(c == '-') w = -1, c = getchar();
    while(c >= '0' && c <= '9') x = (x<<3) + (x<<1) + c - '0', c = getchar();
    return x * w;
}
struct Node{int idx,deep;}a[MAXN];
int N,x,ans,T;
int fa[MAXN],mark[MAXN];
vector <int> G[MAXN];
inline bool comp(Node& a, Node& b){ return a.deep > b.deep; }
void Dfs(int x, int father, int deep){
    int sz = G[x].size(),v;
    fa[x] = father;
    a[++T] = (Node){x, deep};
    for(int i = 0; i < sz; ++i){
        v = G[x][i];
        if(v == father) continue;
        Dfs(v, x, deep+1);
    }
}
inline void MarkDown(int u){
    ++ans;
    int sz = G[u].size(),v,__sz;
    mark[u] = 1;
    for(int i = 0; i < sz; ++i){
        v = G[u][i], mark[v] = 1;
        __sz = G[v].size();
        for(int j = 0; j < __sz; ++j) mark[G[v][j]] = 1;
    }
    u = fa[u];
    mark[u] = 1, mark[fa[u]] = 1;
    sz = G[u].size();
    for(int i = 0; i < sz; ++i) mark[G[u][i]] = 1;
}
int main(){
//    freopen(".in","r",stdin);
    N=r;
    for(int i = 2; i <= N; ++i){
        x=r;
        G[i].push_back(x), G[x].push_back(i);
    }
    Dfs(1, 0, 1);
    sort(a+1,a+T+1,comp);
    int u,v,sz;
    for(int i = 1; i <= T; ++i){
        u = a[i].idx;
        if(mark[u]) continue;
        if(fa[fa[u]]) MarkDown(fa[fa[u]]);
        else{
            if(fa[u]) MarkDown(fa[u]);
            else MarkDown(u);
        }
    }
    printf("%d", ans);
    return 0;
}

 

posted @ 2018-07-28 10:07  DennyQi  阅读(301)  评论(0编辑  收藏  举报