BZOJ 1217 [HNOI2003]消防局的设立 【贪心+dfs】

BZOJ 1217  [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
 
 
题解:
消防局的范围为 <=2,所以每隔4个单位设一个最优。
所以如果节点到离他最新的消防局有 >=5 的距离,那么这个节点就设为最新消防局。
再注意的就是边界:边界上只要距离 >=3 就要设。
 
代码:
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int MAXN = 1010;
 4 int tot=0,ans=0;
 5 int first[MAXN],nxt[MAXN<<1],f[MAXN];
 6 struct node{
 7     int from,to;
 8 }es[MAXN<<1];
 9 void build(int ff,int tt)
10 {
11     es[++tot]=(node){ff,tt};
12     nxt[tot]=first[ff];
13     first[ff]=tot;
14 }
15 void dfs(int x,int p=-1)
16 {
17     int maxn=-MAXN,minn=MAXN;
18     for (int i=first[x]; i!=-1; i=nxt[i])
19     {
20         int v=es[i].to;
21         if (v!=p)
22         {
23             dfs(v,x);
24             maxn=max(f[v],maxn);
25             minn=min(f[v],minn);
26         }
27     }
28     if (maxn+minn<=3)
29       f[x]=minn+1;
30     else f[x]=maxn+1;
31     if (minn==MAXN) f[x]=3;
32     if (f[x]==5)
33     {
34         ans++; f[x]=0;
35     }
36     else if (p==-1 && f[x]>=3) ans++;
37 }
38 int main()
39 {
40     int n;
41     scanf("%d",&n);
42     memset(first,-1,sizeof first);
43     for (int i=1; i<n; i++)
44     {
45         int v;
46         scanf("%d",&v);
47         v--;
48         build(i,v); build(v,i);
49     }
50     dfs(0);
51     cout<<ans<<endl;
52     return 0;
53 }
View Code

 

 

 

加油加油加油!!!fighting fighting fighting!!!

posted on 2018-07-18 08:03  Frank-King  阅读(245)  评论(0编辑  收藏  举报