Dancepted

Dancing Acceped!

P2279 消防局的设立(贪心+dp)

题目链接:传送门

题目大意:

  给定一棵树(N个基地N-1条边);

  用半径为2的消防局覆盖这N个基地,问最小的消防局数量。

  (树上距离为k的最小覆盖问题)

思路:

  每次贪心地找到不被覆盖的最深的一个节点,在它的祖父处放一个消防局。

  这个消防局所在位置即能将这个节点覆盖到的离它最远的点。

复制代码
#include <bits/stdc++.h>

using namespace std;
const int MAX_N = 1e3 + 5;

int N;
vector <int> Edge[MAX_N];
int dep[MAX_N], fa[MAX_N];
bool vis[MAX_N];

int findlower()
{
    int lower = 0, ind = 0;
    for (int i = 1; i <= N; i++) {
        if (!vis[i] && dep[i] > lower) {
            lower = dep[i];
            ind = i;
        }
    }
    return ind;
}

void update(int x)
{
    x = fa[fa[x]];
    for (int i = 0; i < (int)Edge[x].size(); i++) {
        int y = Edge[x][i];
        vis[y] = true;
        for (int j = 0; j < (int)Edge[y].size(); j++) {
            int z = Edge[y][j];
            vis[z] = true;
        }
    }
}

int solve()
{
    memset(vis, false, sizeof vis);
    int ans = 0;
    int cur = findlower();
    while (cur) {
        update(cur);
        ans++;
        cur = findlower();
    }
    return ans;
}

void build(int x)//不妨把编号为1的点当作根节点
{
    for (int i = 1; i <= N; i++) {
        dep[i] = -1;
        fa[i] = i;
    }
    dep[x] = 1;
    queue <int> Q;
    Q.push(x);
    while (!Q.empty()) {
        int u = Q.front(); Q.pop();
        for (int i = 0; i < (int)Edge[u].size(); i++) {
            int v = Edge[u][i];
            if (dep[v] < 0) {
                dep[v] = dep[u] + 1;
                fa[v] = u;
                Q.push(v);
            }
        }
    }
}

int main()
{
    cin >> N;
    for (int u = 2; u <= N; u++) {
        int v;
        cin >> v;
        Edge[u].push_back(v);
        Edge[v].push_back(u);
    }
    int ans = N;
    build(1);
    ans = min(ans, solve());
    cout << ans << endl;
    return 0;
}
View Code
复制代码

 

  前面有点想多了,因为题目中给出的ai < i,所以不需要build直接拿题目中给的树来用就好了。。

  不过也无伤大雅。

  然后是膜大佬学到的代码:

  求树上距离为k的最小覆盖都可以这样做:

  (时间复杂度为O(N * k))

复制代码
#include <bits/stdc++.h>

using namespace std;
const int MAX_N = 1e3 + 5;
const int INF = 0x3f3f3f3f;

struct Node{
    int dep, ind;
    Node(int d = 0, int i = 0) : dep(d), ind(i) {}
    bool operator < (const Node& x) const {
        return dep > x.dep;
    }
}nodes[MAX_N];

int fa[MAX_N], dis[MAX_N];

int main()
{
    int N;
    cin >> N;
    nodes[1] = Node(0, 1);
    fa[1] = 1;
    dis[1] = INF;
    for (int i = 2; i <= N; i++) {
        scanf("%d", fa+i);
        dis[i] = INF;
        nodes[i].ind = i;
        nodes[i].dep = nodes[fa[i]].dep + 1;
    }
    sort(nodes+1, nodes+N+1);
    int ans = 0;
    for (int i = 1; i <= N; i++) {
        int u = nodes[i].ind;
        int v = fa[u];
        int w = fa[v];
        if (dis[u] > 2 && dis[v] > 1 && dis[w] > 0) {
            ans++;
            dis[u] = 2;
            dis[v] = min(dis[v], 1);
            dis[w] = min(dis[w], 0);
            dis[fa[w]] = min(dis[fa[w]], 1);
            dis[fa[fa[w]]] = min(dis[fa[fa[w]]], 2);
        }
    }
    cout << ans << endl;
    return 0;
}
View Code
复制代码

  

 

posted on   Danceped  阅读(287)  评论(0编辑  收藏  举报

编辑推荐:
· 智能桌面机器人:用.NET IoT库控制舵机并多方法播放表情
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
阅读排行:
· 手把手教你在本地部署DeepSeek R1,搭建web-ui ,建议收藏!
· 新年开篇:在本地部署DeepSeek大模型实现联网增强的AI应用
· Janus Pro:DeepSeek 开源革新,多模态 AI 的未来
· 互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(三):用.NET IoT库
· 【非技术】说说2024年我都干了些啥
< 2025年1月 >
29 30 31 1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31 1
2 3 4 5 6 7 8

导航

统计

点击右上角即可分享
微信分享提示