题目https://www.luogu.org/problemnew/show/P2279

题意:一棵树。在节点处建消防站,可以覆盖与他距离在2之内的节点。问最少要建多少个消防站,可以覆盖所有的节点。

思路:有一种贪心的思路,看大部分题解都是这样。

如果要覆盖当前节点(自己不建),那么可能是父亲,兄弟,祖父建了。

但是我们发现,在祖父建覆盖的范围比父亲兄弟要更广一些。所以就贪心的取深度最深的节点,在他的祖父处建一个。

因为想练dp所以没写贪心的。

看结构感觉是树形dp。$dp[i]$表示以$i$为根的子树的情况,想再开一维表示$i$有没有建。后来发现状态好像并不够。

因为只考虑子树的话,当前节点$i$不被覆盖也没关系,他可以被他的父亲或祖先覆盖。

所以大情况分成两种,$i$被覆盖和$i$没被覆盖。

其中$i$被覆盖可以是因为$i$自己建了,也可以是因为有一个儿子建了或者是有一个孙子建了。所以这里有三种状态。

$i$没被覆盖还可以分成只有$i$没被覆盖和$i$和儿子都没有被覆盖。这里又是两种状态。

所以总共是5中状态:

$dp[i][0],在i处建$

$dp[i][1], i处不建但i至少有一个儿子建了$

$dp[i][2],i和儿子都不建但至少有一个孙子建了$

$dp[i][3],自己还没被覆盖,儿子已经被覆盖$

$dp[i][4], 自己和儿子都还没被覆盖$

转移方程:

$dp[i][0] = 1 + \sum min(dp[son][0...4])$每一个儿子的任何一种状态都可以。所以每个儿子都取5种状态的最小的。

$dp[i][1] = min(dp[son1][0] + \sum_(son != son1) min(dp[son][0...3]))$,这里一个巧妙的处理方法是先将每一个儿子的$min(dp[son][0...3])$加上,在找到最小的$dp[son][0]-min(dp[son][0...3])$最后加上。

$dp[i][2] = min(dp[son1][1] + \sum_(son!=son1)(min(dp[son][0...2]))$,此时如果son不在子树被覆盖的话,别的节点也reach不到了。处理方法和上面也一样。

$dp[i][3] = \sum min(dp[son][0...2])$

$dp[i][4] = \sum min(dp[son][0...3]$

 #include<cstdio>
#include<cstdlib>
#include<map>
#include<set>
#include<cstring>
#include<algorithm>
#include<vector>
#include<cmath>
#include<stack>
#include<queue>
#include<iostream> #define inf 0x3f3f3f3f
using namespace std;
typedef long long LL;
typedef pair<int, int> pr; int n;
const int maxn = ;
int fa[maxn];
vector<int>son[maxn];
int dp[maxn][]; void dfs(int rt)
{
if(son[rt].size() == ){
dp[rt][] = ;
dp[rt][] = dp[rt][] = inf;
dp[rt][] = dp[rt][] = ;
return;
}
dp[rt][] = ;
int maxson = inf, maxgs = inf;
for(int i = ; i < son[rt].size(); i++){
dfs(son[rt][i]);
int tmp1 = inf, tmp2 = inf, tmp3 = inf;
for(int j = ; j < ; j++){
tmp1 = min(tmp1, dp[son[rt][i]][j]);
if(j < )tmp2 = min(tmp2, dp[son[rt][i]][j]);
if(j < )tmp3 = min(tmp3, dp[son[rt][i]][j]);
}
dp[rt][] += tmp1;
dp[rt][] += tmp2;
maxson = min(maxson, dp[son[rt][i]][] - tmp2);
maxgs = min(maxgs, dp[son[rt][i]][] - tmp3);
dp[rt][] += tmp3;
dp[rt][] += tmp3;
dp[rt][] += tmp2;
}
dp[rt][] += maxson;
dp[rt][] += maxgs; } int main()
{
scanf("%d", &n);
for(int i = ; i <= n; i++){
scanf("%d", &fa[i]);
son[fa[i]].push_back(i);
}
dfs();
printf("%d\n", min(dp[][], min(dp[][], dp[][]))); }

洛谷P2279 消防局的设立【树形dp】的更多相关文章

  1. 洛谷P2279消防局的设立

    传送门啦 一个很摸不清头脑的树形dp 状态: $ dp[i][0] $ :选自己 $ dp[i][1] $ :选了至少一个儿子 $ dp[i][2] $ :选了至少一个孙子 ------------- ...

  2. 洛谷P2279 消防局的设立 [HNOI2003] 贪心

    正解:贪心 解题报告: 传送门! 这题贪心得挺显然的,,,?居然能有蓝,,,是蓝题太水了嘛,,,? 简单说下,这题一看到就能想到,对最低的没被覆盖到的点给它的祖父建一个消防局 没了? 哦这题实现还挺有 ...

  3. 洛谷 P3177 [HAOI2015]树上染色 树形DP

    洛谷 P3177 [HAOI2015]树上染色 树形DP 题目描述 有一棵点数为 \(n\) 的树,树边有边权.给你一个在 \(0 \sim n\)之内的正整数 \(k\) ,你要在这棵树中选择 \( ...

  4. P2279 [HNOI2003]消防局的设立[树形dp]

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

  5. 洛谷P1040 加分二叉树(树形dp)

    加分二叉树 时间限制: 1 Sec  内存限制: 125 MB提交: 11  解决: 7 题目描述 设一个n个节点的二叉树tree的中序遍历为(l,2,3,...,n),其中数字1,2,3,...,n ...

  6. 洛谷P4438 道路 [HNOI/AHOI2018] 树形dp

    正解:树形dp 解题报告: 传送门! 昂首先看懂题目趴QwQ大概就是说有棵满二叉树,有n个叶子节点(乡村)和n-1个非叶子节点,然后这棵树的每个节点有三个属性abc,对每个非叶子节点可以从与子节点的两 ...

  7. 洛谷 P4201 设计路线 [NOI2008] 树形dp

    正解:树形dp 解题报告: 大概是第一道NOI的题目?有点激动嘻嘻 然后先放个传送门 先大概港下这题的题意是啥qwq 大概就是给一棵树,然后可以选若干条链把链上的所有边的边权变成0,但是这些链不能有交 ...

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

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

  9. 洛谷 P3267 [JLOI2016/SHOI2016]侦察守卫(树形dp)

    题面 luogu 题解 树形\(dp\) \(f[x][y]表示x的y层以下的所有点都已经覆盖完,还需要覆盖上面的y层的最小代价.\) \(g[x][y]表示x子树中所有点都已经覆盖完,并且x还能向上 ...

随机推荐

  1. 并行forearch的使用及测试(Parallel.Foreach)

    using System; using System.Collections.Generic; using System.Diagnostics; using System.Threading.Tas ...

  2. Android虚拟机安装apk

    将apk放入platform-tools 打开虚拟机之后 进入该目录执行命令

  3. RocketMQ之六:RocketMQ消息存储

    一.RocketMQ的消息存储基本介绍 先看一张图: 1.Commit log存储消息实体.顺序写,随机读.2.Message queue存储消息的偏移量.读消息先读message queue,根据偏 ...

  4. sqlserver交换数据行中的指定列

    <!-- 次序上移下移 --> <update id="upOrDown" parameterType="java.util.Map"> ...

  5. jenkins sonarqube 代码检测

    #jenkins插件: SonarQube Scanner #Jenkins配置 Task to run:scan #Analysis properties: sonar.projectKey=ser ...

  6. Python基础 第7章 再谈抽象

    1. 1 多态 多态,即便不知道变量指向的是哪种对象,也能对其执行操作,且操作的行为将随对象所属的类型(类)而异. 1.2 多态与方法 当无需知道对象是什么样的就能对其执行操作时,都是多态在起作用. ...

  7. docker 实践三:操作容器

    在学习了 docker 镜像的内容后,我们在来看 docker 的另一个核心点:容器. 注:环境为 CentOS7,docker 19.03 docker 的容器是镜像的一个运行实例.docker 镜 ...

  8. spring cloud微服务实践四

    spring cloud的hystrix还有一个配搭的库hystrix-dashboard,它是hystrix的一款监控工具,能直观的显示hystrix响应信息,请求成功率等.但是hystrix-da ...

  9. 【搜索+set去重】Balance Scale

    Balance Scale 题目描述 You, an experimental chemist, have a balance scale and a kit of weights for measu ...

  10. 游记-pkupc&cts2019

    Day0 和boshi.Rayment组的队,昨天听学长说这次比赛可以加学分,他们信科的大部分人都会参加,估摸有两百多支队伍--然而奖品只有不到一百份 我要奖品呐! 上午十一点半到的北京,拉着行李提着 ...