BZOJ1217: [HNOI2003]消防局的设立

Description

2020年,人类在火星上建立了一个庞大的基地群,总共有n个基地。
起初为了节约材料,人类只修建了n-1条道路来连接这些基地,并且每两个基地都能够通过道路到达,所以所有的基地形成了一个巨大的树状结构。
如果基地A到基地B至少要经过d条道路的话,我们称基地A到基地B的距离为d。
由于火星上非常干燥,经常引发火灾,人类决定在火星上修建若干个消防局。
消防局只能修建在基地里,每个消防局有能力扑灭与它距离不超过2的基地的火灾。
你的任务是计算至少要修建多少个消防局才能够确保火星上所有的基地在发生火灾时,消防队有能力及时扑灭火灾。

Input

第一行为n,表示火星上基地的数目。N<=1000
接下来的n-1行每行有一个正整数,其中文件第i行的正整数为a[i],表示从编号为i的基地到编号为a[i]的基地之间有一条道路,为了更加简洁的描述树状结构的基地群,有a[i] < i

Output

仅有一个正整数,表示至少要设立多少个消防局才有能力及时扑灭任何基地发生的火灾。

Sample Input

6
1
2
3
4
5

Sample Output

2

题解Here!

各大神犇都用的是树形$DP$。。。

不会树形$DP$的我瑟瑟发抖。。。

其实是一个贪心:找最低没被覆盖到的点,并在它的祖父处设一个消防站。

考虑到这个点的所有子孙后代都已经被覆盖了,因此这时覆盖祖父能盖到更多额外的点,并保证结果不会更差。

很多思路是用$DFS$或堆求取最低节点,实际上没必要,只要预处理出深度(边输入边处理)并排序。

然后碰到已覆盖就跳过,未覆盖就在祖父处设消防站,并且$ans++$即可。

问题在于怎样才能判断这个点覆盖到了没有。

有两种情况很好解决:

1. 儿子或孙子覆盖他:可以在在儿子处设站时就标记它。

2. 父亲或祖父覆盖他:可以用儿子对父亲的映射$fa[i]$来解决。

但是问题在于兄弟:

我们可以用$dis$数组维护$\text{离i最近的消防站到i的距离}$,当$dis[fa[i]]==1$时,就能确定它是否被覆盖。

附:

这种方法的普适性很强,可以解决半径为$k$的最小覆盖问题,而且不用存图。

这时只需要把维护$\text{父亲和爷爷}$改成维护$\text{上位k位祖先}$即可,复杂度$O(NK)$,常数也很小。

然后就可以不用想$DP$。

附代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#define MAXN 1010
using namespace std;
int n,ans=0;
int fa[MAXN],deep[MAXN],rk[MAXN],dis[MAXN];
inline int read(){
int date=0,w=1;char c=0;
while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
return date*w;
}
inline bool cmp(const int &p,const int &q){
return deep[p]>deep[q];
}
void work(){
for(int i=1;i<=n;i++){
int w=rk[i],u=fa[w],v=fa[u];
dis[w]=min(dis[w],min(dis[u]+1,dis[v]+2));
if(dis[w]>2){
ans++;
dis[v]=0;
dis[fa[v]]=min(dis[fa[v]],1);
dis[fa[fa[v]]]=min(dis[fa[fa[v]]],2);
}
}
printf("%d\n",ans);
}
void init(){
n=read();
rk[1]=deep[1]=1;
dis[1]=dis[0]=n;
for(int i=2;i<=n;i++){
fa[i]=read();
deep[i]=deep[fa[i]]+1;
rk[i]=i;
dis[i]=n;
}
sort(rk+1,rk+n+1,cmp);
}
int main(){
init();
work();
return 0;
}

BZOJ1217: [HNOI2003]消防局的设立的更多相关文章

  1. bzoj1217: [HNOI2003]消防局的设立 [树形dp]

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

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

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

  3. BZOJ 1217: [HNOI2003]消防局的设立( 贪心 )

    一个简单的贪心, 我们只要考虑2个消防局设立的距离为5时是最好的, 因为利用最充分. 就dfs一遍, 再对根处理一下就可以了. 这道题应该是SGU某道题的简化版...这道题距离只有2, 树型dp应该也 ...

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

    P2279 [HNOI2003]消防局的设立考场上想出了贪心策略,但是处理细节时有点问题,gg了.从(当前深度最大的节点)叶子节点往上跳k个,在这里设消防局,并从消防局遍历k个距离,标记上. #inc ...

  5. [HNOI2003]消防局的设立 (贪心)

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

  6. [luogu]P2279 [HNOI2003]消防局的设立[贪心]

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

  7. 【洛谷P2279】[HNOI2003]消防局的设立

    消防局的设立 题目链接 贪心:每次取出深度最大的节点,若没有被覆盖到,要想覆盖它, 最优的做法显然是将它的爷爷设为消防局 (因为该节点深度为最大,选兄弟.父亲所覆盖的节点,选了爷爷后都能够覆盖) 用优 ...

  8. BZOJ1217或洛谷2279 [HNOI2003]消防局的设立

    BZOJ原题链接 洛谷原题链接 该题有两种做法,树形\(DP\)和贪心. 先讲贪心. 先将所有点按深度从大到小排序,然后从大到小依次取出点,若已经被覆盖则跳过,否则就在它的祖父点建立消防站. 考虑如何 ...

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

    我对贪心的理解:https://www.cnblogs.com/AKMer/p/9776293.html 题目传送门:https://www.lydsy.com/JudgeOnline/problem ...

随机推荐

  1. eclipse启动Tomcat时报错:严重: Exception loading sessions from persistent storage

    我的项目工程是Spring+hibernate+structs  1.0,最近启动tomcat时多次遇到如下异常: 严重: IOException while loading persisted se ...

  2. MFC中 CString类型用fprintf 函数写到文件中乱码的解决办法

    在上一篇中记录了用fprintf函数写内容到文件中的方法,但是发现了问题:产生的文件字符串有乱码现象. 解决办法:用_ftprintf函数 另外,据说: unicode的话要用fwprintf    ...

  3. JS: document.getElementBy(), setInerval()

    ylbtech-JavaScript-DOM document.getElementBy(),setInerval() 1.A,document.getElementBy()返回顶部 document ...

  4. Esper epl语句实验

    基础代码见下,下文列举的实验都是在此程序基础上改动. all,snapshot,first String epl = "select * from appTable.win:time(5 s ...

  5. grep 精确匹配

    使用grep实现精确过滤的五种方法 (1)当被过滤的内容占据一行时 [root@MySQL scripts]# cat oldboy.log        200 0200 2000 [root@My ...

  6. 又一次认识java(九) ---- 内部类

    注意注意!! ! 前排提示!!.本篇文章过长,最好收藏下来慢慢看.假设你之前对内部类不是非常熟悉,一次性看完,大概你会懵逼. . . 1. 内部类概述 一个类的定义放在还有一个类的内部,这个类就叫做内 ...

  7. 记录MySQL运行的SQL

    对照Oracle功能去学习Mysql总会发现亮点 Oracle中通过日志挖掘这一技能,能够找到以前运行过的全部记录: Mysql中也提供了3种方法{验证过的,我会记录详细做法} 方法1:{已验证} 记 ...

  8. EAI G4-lidar ROS配置

    (1)使用命令创建 ydlidar_ws 工作空间,并将 G4 资料包内的 ROS 驱动包 ydlidar 下载到ydlidar_ws/src 目录下,切换到 ydlidar_ws 工作空间下并重新进 ...

  9. asp.net core 系列之Reponse caching之cache in-memory (2)

    这篇文章(主要翻译于官网,水平有限,见谅)讲解asp.net core 中的 Cache in-memory (内存缓存). Cache in-memory in ASP.NET Core Cachi ...

  10. SpringBoot开启https以及http重定向

    一.使用JDK keytool创建SSL证书 进入$JAVA_HOME/bin目录,运行以下命令 keytool -genkey -alias WeChatAppletsDemo -keypass - ...