【洛谷2279】[HNOI2003] 消防局的设立(贪心)
大致题意: 给你\(N\)个点(其中\(1\)号点为根),并告诉你编号为\(2\sim N\)的点的父亲(\(fa[i]<i\)),现在要在树上选择尽量少的关键点(消防局),使得任意一个点到离它最近的关键点(有可能是它自己)的距离不超过\(2\),求最少选择的点数。
考虑贪心
很显然,这是一道贪心题。
我们可以将这棵树的节点按照\(BFS\)序依次压入栈中(因为这样可以确保先放入的元素深度小)。每次取出栈顶的元素,若它没有被打过标记它周围距离不超过\(2\)的点中有消防局,就说明要建一个新的消防局。
此时就需要将\(ans\)加\(1\),按照贪心的思路,应让消防局的深度越小越好,所以给离它祖父距离不超过\(2\)的所有点打上标记即可。
代码
#include<bits/stdc++.h>
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define LL long long
#define N 1000
using namespace std;
int n,m,ee=0,top,ans=0,lnk[N+5],fa[N+5],Stack[N+5],vis[N+5]={0},flag[N+5]={0};
struct edge
{
int to,nxt;
}e[2*N+5];
inline char tc()
{
static char ff[100000],*A=ff,*B=ff;
return A==B&&(B=(A=ff)+fread(ff,1,100000,stdin),A==B)?EOF:*A++;
}
inline void read(int &x)
{
x=0;int f=1;char ch;
while(!isdigit(ch=tc())) if(ch=='-') f=-1;
while(x=(x<<3)+(x<<1)+ch-'0',isdigit(ch=tc()));
x*=f;
}
inline void write(LL x)
{
if(x<0) putchar('-'),x=-x;
if(x>9) write(x/10);
putchar(x%10+'0');
}
inline void add(int x,int y)
{
e[++ee]=(edge){y,lnk[x]},lnk[x]=ee;
}
inline void reset(int x,int dis)//给距离不超过2的点打上标记
{
if(dis>2) return;//如果距离超过2,就退出
flag[x]=1;//给这个点标记为距离它不超过2的点中有消防局
for(register int i=lnk[x];i;i=e[i].nxt) reset(e[i].to,dis+1);//给与当前节点相邻的点进行reset()操作
}
inline void BFS()//一个BFS的过程
{
register int i,j;
for(i=1;i<=top;++i)//BFS,将树上的节点按照BFS序压入栈
for(j=lnk[i];j;j=e[j].nxt)
if(!vis[e[j].to]) vis[e[j].to]=1,Stack[++top]=e[j].to;
fa[1]=1;//方便之后的操作,初始化1号节点(根节点)的父亲为自己
while(top)
{
int k=Stack[top--];//取出栈顶的元素
if(flag[k]) continue;//如果当前节点已经被打过标记,就跳过当前节点
else ++ans;//否则,说明要新建一个消防局
reset(fa[fa[k]],0);//对离它祖父距离不超过2的节点打标记
}
}
int main()
{
register int i;
for(read(n),i=2;i<=n;++i) read(fa[i]),add(i,fa[i]),add(fa[i],i);
vis[Stack[top=1]=1]=1,BFS();//初始化,将1号节点放入栈中
return write(ans),0;
}
【洛谷2279】[HNOI2003] 消防局的设立(贪心)的更多相关文章
- BZOJ1217或洛谷2279 [HNOI2003]消防局的设立
BZOJ原题链接 洛谷原题链接 该题有两种做法,树形\(DP\)和贪心. 先讲贪心. 先将所有点按深度从大到小排序,然后从大到小依次取出点,若已经被覆盖则跳过,否则就在它的祖父点建立消防站. 考虑如何 ...
- 洛谷 2279 [HNOI2003]消防局的设立
Description 2020年,人类在火星上建立了一个庞大的基地群,总共有n个基地.起初为了节约材料,人类只修建了n-1条道路来连接这些基地,并且每两个基地都能够通过道路到达,所以所有的基地形成了 ...
- 洛谷 P2279 [HNOI2003]消防局的设立 (树形dp or 贪心)
一看到这道题就知道是树形dp 之前做过类似的题,只不过保护的范围是1 所以简单很多. 这道题保护的范围是2,就复杂了很多. 我就开始列状态,然后发现竟然有5种 然后我就开始列方程. 但是我考虑的时候是 ...
- 洛谷P2279 [HNOI2003]消防局的设立
题目描述 2020年,人类在火星上建立了一个庞大的基地群,总共有n个基地.起初为了节约材料,人类只修建了n-1条道路来连接这些基地,并且每两个基地都能够通过道路到达,所以所有的基地形成了一个巨大的树状 ...
- 洛谷 P2279 [HNOI2003]消防局的设立
题目描述 2020年,人类在火星上建立了一个庞大的基地群,总共有n个基地.起初为了节约材料,人类只修建了n-1条道路来连接这些基地,并且每两个基地都能够通过道路到达,所以所有的基地形成了一个巨大的树状 ...
- 洛谷 P2279 [HNOI2003]消防局的设立 题解
每日一题 day34 打卡 Analysis 这道题的正解本来是树形dp,但要设5个状态,太麻烦了.于是我就用贪心试图做出此题,没想到还真做出来了. 考虑当前深度最大的叶子结点,你肯定要有一个消防局去 ...
- Luogu 2279 [HNOI2003]消防局的设立 - 贪心
Description 给定一棵树形图, 建若干个消防站, 消防站能够覆盖到距离不超过2的点, 求最少需要建几个消防站才能覆盖所有点 Solution 从深度最深的点开始, 在它的爷爷节点上建, 每建 ...
- BZOJ 1217: [HNOI2003]消防局的设立( 贪心 )
一个简单的贪心, 我们只要考虑2个消防局设立的距离为5时是最好的, 因为利用最充分. 就dfs一遍, 再对根处理一下就可以了. 这道题应该是SGU某道题的简化版...这道题距离只有2, 树型dp应该也 ...
- [HNOI2003]消防局的设立 (贪心)
[HNOI2003]消防局的设立 题目描述 2020年,人类在火星上建立了一个庞大的基地群,总共有n个基地.起初为了节约材料,人类只修建了n-1条道路来连接这些基地,并且每两个基地都能够通过道路到达, ...
- [luogu]P2279 [HNOI2003]消防局的设立[贪心]
[luogu]P2279 [HNOI2003]消防局的设立 题目描述 2020年,人类在火星上建立了一个庞大的基地群,总共有n个基地.起初为了节约材料,人类只修建了n-1条道路来连接这些基地,并且每两 ...
随机推荐
- Spark Executor 概述
Spark Executor 工作原理: 1. 在CoarseGrainedExecutorBackend启动时向Driver注册Executor,其实质是注册ExecutorBackend实例,和E ...
- 剑指Offer的学习笔记(C#篇)-- 旋转数组的最小数字
题目描述 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转. 输入一个非减排序的数组的一个旋转,输出旋转数组的最小元素. 例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋 ...
- 分层图最短路【bzoj2763】: [JLOI2011]飞行路线
bzoj2763: [JLOI2011]飞行路线 Description Alice和Bob现在要乘飞机旅行,他们选择了一家相对便宜的航空公司.该航空公司一共在n个城市设有业务,设这些城市分别标记为0 ...
- PAT甲级——1095 Cars on Campus (排序、映射、字符串操作、题意理解)
本文同步发布在CSDN:https://blog.csdn.net/weixin_44385565/article/details/93135047 1095 Cars on Campus (30 分 ...
- Polycarp's Pockets(思维)
Polycarp has nn coins, the value of the ii-th coin is aiai. Polycarp wants to distribute all the coi ...
- spark_load csv to hive via hivecontext
//prepare csv year,make,model,comment,blank "2012","Tesla","S","N ...
- Gym 100971B Derangement
要求改换序列,使得没有位置是a[i] == i成立.输出最小要换的步数 首先把a[i] == i的位置记录起来,然后两两互相换就可以了. 对于是奇数的情况,和它前一个换或者后一个换就可以,(注意前一个 ...
- 美国一家科技公司毕威拓(Pivotal)规定员工在早上9点06分准时上班,以提高工作效率。
美国一家科技公司毕威拓(Pivotal)规定员工在早上9点06分准时上班,以提高工作效率. 据<英国广播公司BBC>报道,美国科技公司毕威拓(Pivotal)的员工每天都要在9点06分准时 ...
- (转)认识 Linux 文件系统
7.1 认识 Linux 文件系统 原文:https://wizardforcel.gitbooks.io/vbird-linux-basic-4e/content/59.html Linux 最传统 ...
- calendar 类 用法
add()和roll()区别 一.Calendar 月份从 0-11,要表示8月,应该传入7 . 二.set() 会自动转换为合法的日期,如 set(1999,8,31) 表示的是1999-09-3 ...