• 洛谷 2279 [HNOI2003]消防局的设立


    Description

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

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

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

    Input

    输入文件名为input.txt。

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

    Output

    输出文件名为output.txt

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

    Sample

    输入样例#1:
    6
    1
    2
    3
    4
    5
    
    输出样例#1:
    2


    Solution
    方法1:贪心
    转化为一棵以1为根节点的有根树,考虑深度最大的节点,当覆盖它的节点为它的父节点的父节点时,是最优的(反证法)

    举个栗子,考虑节点5时,1,3,4都可以覆盖它,但是3,4能覆盖的节点1都可以覆盖(因为3,4的深度小一点,覆盖的点的深度也小一点,但是5是深度最大的点,没有深度更大的点了)

    所以可以以深度为关键字排序,每次找到深度最大的节点,从这个节点出发走4个距离的点都标为已覆盖
    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    #define nn 1011
    using namespace std;
    int vis[nn],dis[nn],fir[nn],nxt[nn<<1],to[nn<<1],e=0;
    struct node{
    	int th,dis;
    	bool operator <(const node &v) const{
    		return dis<v.dis;
    	}
    }o;
    priority_queue<node> q;
    int read()
    {
    	int ans=0,f=1;char ch=getchar();
    	while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();}
    	while(isdigit(ch)) {ans=ans*10+ch-'0';ch=getchar();}
    	return ans*f;
    }
    void add(int u,int v)
    {
    	nxt[++e]=fir[u];fir[u]=e;to[e]=v;
    	nxt[++e]=fir[v];fir[v]=e;to[e]=u;
    }
    void solve(int x,int fa,int use)
    {
    	vis[x]=1;
    	if(use>=4)
    	  return;
    	for(int i=fir[x];i;i=nxt[i])
    	  if(to[i]!=fa)
    	    solve(to[i],x,use+1);
    }
    int main()
    {
    	int n,fa,ans=0;
    	n=read();
    	o.dis=0;o.th=1;       ////
    	q.push(o);
    	for(int i=2;i<=n;i++)
    	{
    		fa=read();
    		dis[i]=dis[fa]+1;
    		o.dis=dis[i];o.th=i;
    		q.push(o);
    		add(i,fa);
    	}
    	while(!q.empty())
    	{
    		o=q.top();q.pop();
    		if(!vis[o.th])
    		{
    			solve(o.th,0,0);
    		    ans++;
    		}
    	}
    	printf("%d",ans);
    	return 0;
    }


    方法2:树形dp
  • 相关阅读:
    关于c#.net 使用自动生成的TableAdapter类的Insert、update方法无效
    .net 字符流下载 迅雷下载问题
    win7 64位系统下使用Oracle的问题
    使用vs2010发布.net framework2.0的网站出现的 分析器错误
    c博客作业我的第一篇博客
    C博客作业01分支,顺序结构1
    机器学习特训营前四次课总结
    ASP.NET应用程序与页面生命周期
    asp.net 获取文件的详细属性,大小,修改日期,所在位置等
    Json string value cannot have line breaks(解决方法)
  • 原文地址:https://www.cnblogs.com/charlotte-o/p/7637772.html
Copyright © 2020-2023  润新知