LuoguP2279

題意:給你一棵樹,選樹上最少的點將整棵樹覆蓋。選的點可以覆蓋距離爲2以內的所有點。
思路:貪心策略,每次選擇沒被覆蓋的點裏的深度最深的點,選其父親的父親的節點進行覆蓋操作。
代碼:

#include <bits/stdc++.h>

using namespace std;
#define ll long long
#define __ ios::sync_with_stdio(0);cin.tie(0);cout.tie(0)

const int maxn = 10100;
struct pxy {
    int to, next;
} e[maxn];
int head[maxn], cnt, n;
int dep[maxn], fa[maxn];
bool vis[maxn];

void ins(int x, int y) {
    e[++cnt].to = y;
    e[cnt].next = head[x];
    head[x] = cnt;
}

void dfs(int x, int d) {
    dep[x] = d;
    for (int i = head[x]; i; i = e[i].next) {
        if (dep[e[i].to] == 0) {
            dfs(e[i].to, d + 1);
        } else fa[x] = e[i].to;
    }
}

struct yjq {
    int x, d;

    bool operator<(const yjq &b) const {
        return d < b.d;
    }
};

priority_queue<yjq> q;
queue<int> P;

void color(int x) {
    while (!P.empty())P.pop();
    vis[x] = 1;
    for (int i = head[x]; i; i = e[i].next) {
        P.push(e[i].to);
        vis[e[i].to] = 1;
    }
    while (!P.empty()) {
        int u = P.front();
        P.pop();
        for (int i = head[u]; i; i = e[i].next) {
            vis[e[i].to] = 1;
        }
    }
}

int main() {
    __;
    cin >> n;
    for (int i = 1; i < n; ++i) {
        int x;
        cin >> x;
        ins(i + 1, x);
        ins(x, i + 1);
    }
    dfs(1, 1);
    for (int i = 1; i <= n; ++i) {
        q.push({i, dep[i]});
    }
    int ans = 0;
    while (!q.empty()) {
        yjq u = q.top();
        q.pop();
        if (vis[u.x] == 0) {
            int v = u.x;
            if (fa[v])v = fa[v];
            if (fa[v])v = fa[v];
            color(v);
            ans++;
        }
    }
    cout << ans << endl;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章