[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
由于最大消防距离为定值,于是我们可以考虑贪心,每次选择深度最深的一个,在其爷爷处设立一个消防站,并以其爷爷为中心进行dfs,将长度为二的点都打上标记,打上标记将不再处理。
代码(练一下STL):
1 //2017.11.6 2 //greedy 3 #include<iostream> 4 #include<cstdio> 5 #include<cstring> 6 #include<algorithm> 7 #include<queue> 8 using namespace std; 9 inline int read(); 10 namespace lys{ 11 const int N = 1e3 + 7 ; 12 struct egde{ 13 int to; 14 int next; 15 }e[N*3]; 16 struct DEEP{ 17 int node,deep; 18 bool operator < (const DEEP &a) const{ 19 return a.deep>deep; 20 } 21 }; 22 priority_queue<DEEP> q; 23 bool used[N]; 24 int pre[N],fa[N]; 25 int n,cnt; 26 void add(int x,int y){ 27 e[++cnt].to=y;e[cnt].next=pre[x];pre[x]=cnt; 28 e[++cnt].to=x;e[cnt].next=pre[y];pre[y]=cnt; 29 } 30 void dfs(int node,int deep){ 31 q.push((DEEP){node,deep}); 32 int i,v; 33 for(i=pre[node];i;i=e[i].next){ 34 v=e[i].to; 35 if(v==fa[node]) continue ; 36 fa[v]=node; 37 dfs(v,deep+1); 38 } 39 } 40 void dfs1(int node,int deep){ 41 if(deep>2) return ; 42 int i,v; 43 used[node]=true ; 44 for(i=pre[node];i;i=e[i].next){ 45 v=e[i].to; dfs1(v,deep+1); 46 } 47 } 48 int main(){ 49 int u,i; 50 n=read(); 51 for(i=1;i<n;i++){ 52 u=read(); add(u,i+1); 53 } 54 dfs(1,1); 55 cnt=0; 56 while(!q.empty()){ 57 DEEP x=q.top();q.pop(); 58 if(used[x.node]) continue ; 59 if(fa[fa[x.node]]) dfs1(fa[fa[x.node]],0); 60 else dfs1(1,0); 61 cnt++; 62 } 63 printf("%d ",cnt); 64 return 0; 65 } 66 } 67 int main(){ 68 lys::main(); 69 return 0; 70 } 71 inline int read(){ 72 int kk=0,ff=1; 73 char c=getchar(); 74 while(c<'0'||c>'9'){ 75 if(c=='-') ff=-1; 76 c=getchar(); 77 } 78 while(c>='0'&&c<='9') kk=kk*10+c-'0',c=getchar(); 79 return kk*ff; 80 }