洛谷P2279_无根树转有根树+贪心

本文介绍了一种解决在特定树形结构中布局消防站的问题算法。通过将无根树转化为有根树,并采用深度优先搜索来确定消防站的最佳位置,确保所有基地在发生火灾时都能得到覆盖。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目大意:有n个基地,n-1条边,且没两个基地可达。从基地A到基地B至少要经过d条边,则两基地的距离为d。现在要在基地上建消防站,且每个消防站有能力扑灭与它距离不超过2的基地的火灾。问至少要建多少个消防站才能确保所有基地都发生火灾时,能扑灭全部的火

(1)将无根树转化为有根树
(2)找到未被标记且深度最深的点pos
(3)若有符合要求的pos, 就建立一个消防站,然后从点x染色
若pos的深度是1,即为root,则x = pos;
若pos的深度是2,则没有爷节点,那么x = fa[pos];
若pos的深度>2,则有爷节点,那么x = fa[fa[pos]];
(4)重复(2)(3)直到没有符合要求的pos

#include <cstdio>
#include <cstring>

using namespace std;

const int maxn = 1010;

int n, ans;

int to[maxn<<1], next[maxn<<1];//链式前向星
int head[maxn], tot;

int dep[maxn];//深度,用于无根树转化为有根树
int fa[maxn];//father, 初始化为0
int vis[maxn];//标记该点是否染色

void addedge(int u, int v)
{
    ++tot;
    to[tot] = v;
    next[tot] = head[u];
    head[u] = tot;
}

void dfs(int u, int f)//u的fa是f
{
    dep[u] = dep[f] + 1;
    fa[u] = f;
    for(int i = head[u]; i; i = next[i])
        if(to[i] != f)
            dfs(to[i], u);
}

void col(int u, int f, int dis)//记录fa:f避免重复染色
{
    if(dis == 3) return;
    vis[u] = 1;
    for(int i = head[u]; i; i = next[i])
        if(to[i] != f)
            col(to[i], u, dis+1);
}

int main()
{
    int i, x;
    scanf("%d", &n);
    memset(fa, 0, sizeof(fa));
    memset(vis, 0, sizeof(vis));
    memset(head, 0, sizeof(head));
    ans = 0;
    tot = 0;
    for(i = 2; i <= n; ++i)
    {
        scanf("%d", &x);
        addedge(i, x);
        addedge(x, i);
    }
    dfs(1, 0);//无根树转有根树
    while(1)
    {
        int pos = 0, maxdep = 0;
        for(i = 1; i <= n; ++i)
            if(!vis[i] && dep[i] > maxdep)
                maxdep = dep[i], pos = i;
        if(!pos) break;
        ++ans;//建立一个消防站
        //染色
        if(dep[pos] == 1) col(pos, 0, 0);
        else if(dep[pos] == 2) col(fa[pos], 0, 0);
        else col(fa[fa[pos]], 0, 0);
    }
    printf("%d\n", ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值