BZOJ 1217: [HNOI2003]消防局的设立 贪心+dfs

16 篇文章 0 订阅
11 篇文章 0 订阅

BZOJ 1217: [HNOI2003]消防局的设立

在某背景下做了此题。此题有解为树形DP,这里是贪心的题解。

思路:考虑到 一个消防局可以扑灭与他距离 <= 2 的所有点。那么我们每隔4个点放一个消防局是最优的。
在 dfs 中:我们用数组 f[] 标记每个点 某种程度上可以说 abs(f[x]-5) 就是 x 到消防局的距离。当 f[x] == 5 时 那我们另 f[x] == 0 即,把这个看为一个消防局 ans ++;
还有一个地方就是处理一下边界,即开始的点,如果走到了这里而这里距离最近的消防局的距离大于等于3,也就是这里没有被消防局覆盖,那就只能在这里也加上一个消防局了。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;

const int MAXN = 1000 + 10;
int tot = 0, ans = 0;
int first[MAXN], nxt[MAXN << 1], f[MAXN];
struct edge{
    int from, to;
}es[MAXN << 1];

void build(int ff, int tt)
{
    es[++tot] = (edge){ff,tt};
    nxt[tot] = first[ff];
    first[ff] = tot;
}

void dfs(int x, int p = -1)
{
    int maxn = -MAXN, minn = MAXN;
    for(int i = first[x]; i != -1; i = nxt[i])
    {
        int v = es[i].to;
        if(v != p)
        {
            dfs(v, x);
            maxn = max(f[v], maxn);
            minn = min(f[v], minn);
        }
    }
    if(maxn + minn <= 3)
        f[x] = minn + 1;
    else f[x] = maxn + 1;
    if(minn == MAXN)
        f[x] = 3;
    if(f[x] == 5)
    {
        ans ++;
        f[x] = 0;
    }
    else if(p == -1 && f[x] >= 3)
        ans ++;
}

int main()
{
    int n; 
    cin >> n;
    memset(first,-1,sizeof(first));
    for(int i = 1; i < n; i ++)
    {
        int v;
        scanf("%d",&v);
        v --;
        build(i,v);
        build(v,i);
    }
    dfs(0);
    cout << ans << endl;
    return 0;
}

P.S 这种做法 是跟这个博客学的。尊重知识产权从我做起。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值