BZOJ原题链接

洛谷原题链接

该题有两种做法,树形\(DP\)和贪心。

先讲贪心。

先将所有点按深度从大到小排序,然后从大到小依次取出点,若已经被覆盖则跳过,否则就在它的祖父点建立消防站。

考虑如何判断该点是否被覆盖,设数组\(dis[x]\)表示点\(x\)到达离它最近的消防站的距离。

则在扫到一个点时,先用它父亲和祖父的\(dis\)来尝试更新该点的\(dis\),即尝试用父亲或祖父来覆盖该点,若没有被覆盖,则在祖父建立消防站,并更新祖父的父亲和祖父的祖父的\(dis\),这样就能同时将兄弟节点和儿子(孙子)节点覆盖点的情况记录下来。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = 1010;
int de[N], fa[N], po[N], dis[N];
inline int re()
{
int x = 0;
char c = getchar();
bool p = 0;
for (; c < '0' || c > '9'; c = getchar())
p |= c == '-';
for (; c >= '0' && c <= '9'; c = getchar())
x = x * 10 + c - '0';
return p ? -x : x;
}
inline int minn(int x, int y)
{
return x < y ? x : y;
}
bool comp(int x, int y)
{
return de[x] > de[y];
}
int main()
{
int i, x, y, z, n, s = 0;
n = re();
memset(dis, 60, sizeof(dis));
for (de[1] = po[1] = 1, i = 2; i <= n; i++)
{
scanf("%d", &fa[i]);
de[i] = de[fa[i]] + 1;
po[i] = i;
}
sort(po + 1, po + n + 1, comp);
for (i = 1; i <= n; i++)
{
x = po[i];
y = fa[x];
z = fa[y];
dis[x] = minn(dis[x], minn(dis[y] + 1, dis[z] + 2));
if (dis[x] > 2)
{
dis[z] = 0;
s++;
x = fa[z];
y = fa[x];
dis[x] = minn(dis[x], 1);
dis[y] = minn(dis[y], 2);
}
}
printf("%d", s);
return 0;
}

然后是另一种做法,树形\(DP\)。

设\(f[x][k]\)表示以\(x\)为根的子树,\(x\)点在\(k\)状态下建立的消防局总数。

  1. \(k = 0\)表示在\(x\)建立消防局。
  2. \(k = 1\)表示\(x\)至少有一个儿子建立消防局。
  3. \(k = 2\)表示\(x\)至少有一个孙子建立消防局。
  4. \(k = 3\)表示\(x\)的儿子节点全部被覆盖。
  5. \(k = 4\)表示\(x\)的孙子节点全部被覆盖。

前\(3\)种情况保证\(x\)被覆盖,后\(2\)种则不能保证。

设\(y,z\)均为\(x\)儿子。

则有状态转移方程:

\(\qquad\qquad f[x][0] = 1 + \sum\min\{ f[y][0\to 4] \}\)

\(\qquad\qquad f[x][1] = \min\{ f[y][0] + \sum\min\{ f[z][0\to 3]\ (z \neq y) \} \}\)

\(\qquad\qquad f[x][2] = \min\{ f[y][1] + \sum\min\{ f[z][0\to 2]\ (z \neq y) \} \}\)

\(\qquad\qquad f[x][3] = \sum\min\{ f[y][0\to 2] \}\)

\(\qquad\qquad f[x][4] = \sum\min\{ f[y][0\to 3] \}\)

显然对于状态\(0\to 4\),建立的消防局总数依次减小,所以可以优化转移方程:

\(\qquad\qquad f[x][0] = 1 + \sum f[y][4]\)

\(\qquad\qquad f[x][1] = f[x][4] + \min\{ f[y][0] - f[y][3] \}\)

\(\qquad\qquad f[x][2] = f[x][3] + \min\{ f[y][1] - f[y][2] \}\)

\(\qquad\qquad f[x][3] = \sum f[y][2]\)

\(\qquad\qquad f[x][4] = \sum f[y][3]\)

最后答案就是\(f[1][2]\)。

因为贪心的可拓展性较好(可以处理覆盖\(k\)距离的情况),且打起来简单,所以这里就不给出\(DP\)的代码了(其实是懒)。

BZOJ1217或洛谷2279 [HNOI2003]消防局的设立的更多相关文章

  1. 洛谷 2279 [HNOI2003]消防局的设立

    Description 2020年,人类在火星上建立了一个庞大的基地群,总共有n个基地.起初为了节约材料,人类只修建了n-1条道路来连接这些基地,并且每两个基地都能够通过道路到达,所以所有的基地形成了 ...

  2. 洛谷 P2279 [HNOI2003]消防局的设立 (树形dp or 贪心)

    一看到这道题就知道是树形dp 之前做过类似的题,只不过保护的范围是1 所以简单很多. 这道题保护的范围是2,就复杂了很多. 我就开始列状态,然后发现竟然有5种 然后我就开始列方程. 但是我考虑的时候是 ...

  3. 洛谷P2279 [HNOI2003]消防局的设立

    题目描述 2020年,人类在火星上建立了一个庞大的基地群,总共有n个基地.起初为了节约材料,人类只修建了n-1条道路来连接这些基地,并且每两个基地都能够通过道路到达,所以所有的基地形成了一个巨大的树状 ...

  4. 洛谷 P2279 [HNOI2003]消防局的设立

    题目描述 2020年,人类在火星上建立了一个庞大的基地群,总共有n个基地.起初为了节约材料,人类只修建了n-1条道路来连接这些基地,并且每两个基地都能够通过道路到达,所以所有的基地形成了一个巨大的树状 ...

  5. 洛谷 P2279 [HNOI2003]消防局的设立 题解

    每日一题 day34 打卡 Analysis 这道题的正解本来是树形dp,但要设5个状态,太麻烦了.于是我就用贪心试图做出此题,没想到还真做出来了. 考虑当前深度最大的叶子结点,你肯定要有一个消防局去 ...

  6. Luogu 2279 [HNOI2003]消防局的设立 - 贪心

    Description 给定一棵树形图, 建若干个消防站, 消防站能够覆盖到距离不超过2的点, 求最少需要建几个消防站才能覆盖所有点 Solution 从深度最深的点开始, 在它的爷爷节点上建, 每建 ...

  7. luogu 2279 [HNOI2003]消防局的设立 树形dp

    就是细节多一些,思路都非常常规. Code: #include <bits/stdc++.h> #define N 1005 #define inf 1061109567 #define ...

  8. 【BZOJ1217】[HNOI2003]消防局的设立 树形DP

    [BZOJ1217][HNOI2003]消防局的设立 Description 2020年,人类在火星上建立了一个庞大的基地群,总共有n个基地.起初为了节约材料,人类只修建了n-1条道路来连接这些基地, ...

  9. BZOJ1217: [HNOI2003]消防局的设立

    BZOJ1217: [HNOI2003]消防局的设立 Description 2020年,人类在火星上建立了一个庞大的基地群,总共有n个基地. 起初为了节约材料,人类只修建了n-1条道路来连接这些基地 ...

随机推荐

  1. 学JS的心路历程-函式(六)其余参数及预设参数

    今天我们要来介绍ES6新增的其余参数及预设参数! 其余参数rest parameter …numbers可以让我们表示不确定数量的参数,并将其视为一个数组: function getVal(…numb ...

  2. linux下进程查找和杀死

    比如杀死进程中叫  abc的进程 1.ps -ef |grep abc|awk '{print $2}' xargs kill -9 2.kill `pidof abc`        `位于tab键 ...

  3. 05_ssm基础(六)之SpringMVC

    36.springMVC之入门 1.springMVC简介 Spring MVC是基于MVC模式的一个Web框架,它解决WEB开发中常见的问题(参数接收.文件上传.表单验证.国际化.等等),而且使用简 ...

  4. @Scope 注解

    @Scope(value=ConfigurableBeanFactory.SCOPE_PROTOTYPE)这个是说在每次注入的时候回自动创建一个新的bean实例 @Scope(value=Config ...

  5. django创建一个简单的web站点

    一.新建project 使用Pycharm,File->New Project…,选择Django,给project命名 (project不能用test命名)   新建的project目录如下: ...

  6. 全国高校绿色计算大赛 预赛第一阶段(C++)第4关:计算日期

    挑战任务 我们吃的食物都有保质期,现在食品监督管理局想要制作一个能准确计算食品过期日期的小程序,需要请你来进行设计. 例如:A食品在2018年1月1日生产,保质期是20天,则它的过期日期在2018年1 ...

  7. NumPy 统计函数

    NumPy 统计函数 NumPy 提供了很多统计函数,用于从数组中查找最小元素,最大元素,百分位标准差和方差等. 函数说明如下: numpy.amin() 和 numpy.amax() numpy.a ...

  8. numpy.random.uniform()

    numpy.random.uniform均匀分布 2018年06月19日 23:28:03 徐小妹 阅读数:4238   numpy.random.uniform介绍: 1. 函数原型:  numpy ...

  9. layui复选框

    效果图 layui复选框,一个主的复选框控制多个从复选框,主复选框和从复选框的颜色不一样 layui复选框的样式,都是在选然后才会有的,所以直接通过css设置就实现不了了.只可以通过js动态设置 ht ...

  10. mute

    mute - 必应词典 英[mjuːt] n.哑吧:沉默的人:[法律]拒绝答辩的被告人:鸟粪 adj.哑的:缄默无言的:(一时)说不出话的:(猎狗)不叫的 v.排泄:减弱…的声音:柔和…的色调 网络静 ...