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. ETL之Kettle

    Kettle是一款国外开源的ETL工具,纯java编写,可以在Window.Linux.Unix上运行. 说白了就是,很有必要去理解一般ETL工具必备的特性和功能,这样才更好的掌握Kettle的使用. ...

  2. tcp/ip RFC

     http://www.ietf.org/rfc.htmlhttp://www.rfc-editor.org

  3. Data-structures-and-algorithms-interview-questions-and-their-solutions

    https://techiedelight.quora.com/500-Data-structures-and-algorithms-interview-questions-and-their-sol ...

  4. linux基础学习6

    daemon 可以理解成为service   两大类: stand_alone:此 daemon 可以自行单独启动服务,加载到内存后就一直占用内存与系统资源:如 www的httpd ,ftp的vsft ...

  5. GCD和信号量

    GCD 概念不多说,直接上代码.话说也不是什么高深的东东,不过极大简化了代码,一目了然.后面对信号量的记录也采用了相同的原理. //抛出线程 dispatch_async(dispatch_get_g ...

  6. 将Solr的数据存到Hdfs上

    具体官方文档 https://cwiki.apache.org/confluence/display/solr/Running+Solr+on+HDFS 修改solrconfig.xml文件 < ...

  7. 2017.2.15 开涛shiro教程-第二十一章-授予身份与切换身份(一) table、entity、service、dao

    原博客地址:http://jinnianshilongnian.iteye.com/blog/2018398 根据下载的pdf学习. 第二十一章 授予身份与切换身份(一) 1.使用场景 某个领导因为某 ...

  8. Python将JSON格式数据转换为SQL语句以便导入MySQL数据库

    前文中我们把网络爬虫爬取的数据保存为JSON格式,但为了能够更方便地处理数据.我们希望把这些数据导入到MySQL数据库中.phpMyadmin能够把MySQL数据库中的数据导出为JSON格式文件,但却 ...

  9. vue修改数组元素方法

    示例代码 <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UTF- ...

  10. Hadoop1.2.1 全然分布式集群搭建实操笔记

    前期准备工作: 1.改动Linux主机名:/etc/hostname                         ubuntu系统:vi /etc/hostname                 ...