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


    [HNOI2003]消防局的设立

    题目描述

    2020年,人类在火星上建立了一个庞大的基地群,总共有n个基地。起初为了节约材料,人类只修建了n-1条道路来连接这些基地,并且每两个基地都能够通过道路到达,所以所有的基地形成了一个巨大的树状结构。如果基地A到基地B至少要经过d条道路的话,我们称基地A到基地B的距离为d。

    由于火星上非常干燥,经常引发火灾,人类决定在火星上修建若干个消防局。消防局只能修建在基地里,每个消防局有能力扑灭与它距离不超过2的基地的火灾。

    你的任务是计算至少要修建多少个消防局才能够确保火星上所有的基地在发生火灾时,消防队有能力及时扑灭火灾。

    输入输出格式

    输入格式:

    输入文件名为input.txt。

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

    输出格式:

    输出文件名为output.txt

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

    输入输出样例

    输入样例#1:

    6
    1
    2
    3
    4
    5

    输出样例#1:

    2

    Solution

    这道题本来应该是考贪心的,但由于距离为2,所以树形dp也可以做
    本篇主要讲贪心
    首先,看到题目中的这句话

    每个消防局有能力扑灭与它距离不超过2的基地的火灾。

    这要求我们至少在底层的叶子结点一定要有消防局去覆盖它,这个时候有几个选择

    1. 自己本身
    2. 父亲节点
    3. 兄弟节点
    4. 祖父节点

    很显然,前三种情况都可以被最后一种情况包括,即选择最后一种策略不会更劣,那么我们确定了贪心思路:如果我们确定了一个节点需要被覆盖,那么在它的祖父节点设立消防局就可以了

    那么现在问题就是怎么找出那些需要被覆盖的节点?

    我们用一个数组dis[i]表示i节点与离i最近的消防局之间的距离

    初始值因为没有设立消防局,所以设为无限大

    那么我们按深度从大到小排一遍序就可以了,如果当前dis[i]>2,就在祖父节点那里设立消防局
    至于dis[i],可以一边做一边更新

    Code

    #include<bits/stdc++.h>
    #define in(i) (i=read())
    #define rg register
    #define il extern inline
    using namespace std;
    
    const int N=1e3+10;
    
    int read() {
    	int ans=0,f=1; char i=getchar();
    	while(i<'0' || i>'9') {if(i=='-') f=-1; i=getchar();}
    	while(i>='0' && i<='9') ans=ans*10+(i^48),i=getchar();
    	return ans*f;
    }
    
    int n,ans;
    int dep[N],dis[N],id[N],f[N];
    bool cmp(int a,int b) {return dep[a]>dep[b];}
    int main()
    {
    	in(n); id[1]=1,dis[1]=dis[0]=N;
    	for(rg int i=2;i<=n;i++) {
    		in(f[i]); dep[i]=dep[f[i]]+1;//保证f[i]<i
    		id[i]=i,dis[i]=N;
    	}
    	sort(id+1,id+1+n,cmp);
    	for(rg int i=1;i<=n;i++) {
    		int u=id[i],v=f[u],gf=f[v];
    		dis[u]=min(dis[u],min(dis[v]+1,dis[gf]+2));
    		if(dis[u]>2) {
    			dis[gf]=0,ans++;
    			dis[f[gf]]=min(dis[f[gf]],1),dis[f[f[gf]]]=min(dis[f[f[gf]]],2);
    		}
    	}
    	cout<<ans<<endl;
    }
    

    博主蒟蒻,随意转载.但必须附上原文链接

    http://www.cnblogs.com/real-l/

  • 相关阅读:
    android AudioManager AUDIOFOCUS
    uboot环境变量实现分析
    观察者模式总结
    【BZOJ3270】博物馆 概率DP 高斯消元
    从零開始学android&lt;TabHost标签组件.二十九.&gt;
    怎样在Web项目中的service业务层获取项目根路劲
    TexturePacker 算法
    [leetCode 75] Sort Colors
    无人车可能导致器官捐献者短缺以及吸烟率下降:4星|《无人驾驶,十万亿美元的大饼怎么分?》
    如何寻找颠覆式创新的机会,《创新者的窘境》作者二十年磨一剑:4星|《与运气竞争》
  • 原文地址:https://www.cnblogs.com/real-l/p/9722352.html
Copyright © 2020-2023  润新知