首页 > 代码库 > bzoj1217: [HNOI2003]消防局的设立 [树形dp]

bzoj1217: [HNOI2003]消防局的设立 [树形dp]

Description

2020年,人类在火星上建立了一个庞大的基地群,总共有n个基地。起初为了节约材料,人类只修建了n-1条道路来连接这些基地,并且每两个基地都能够通过道路到达,所以所有的基地形成了一个巨大的树状结构。如果基地A到基地B至少要经过d条道路的话,我们称基地A到基地B的距离为d。由于火星上非常干燥,经常引发火灾,人类决定在火星上修建若干个消防局。消防局只能修建在基地里,每个消防局有能力扑灭与它距离不超过2的基地的火灾。你的任务是计算至少要修建多少个消防局才能够确保火星上所有的基地在发生火灾时,消防队有能力及时扑灭火灾。

Input

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

Output

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

Sample Input

6
1
2
3
4
5

Sample Output

2

论状态设计之巧妙
 1 /************************************************************** 2     Problem: 1217 3     User: ZYBGMZL 4     Language: C++ 5     Result: Accepted 6     Time:0 ms 7     Memory:1312 kb 8 ****************************************************************/ 9  10 #include<cstdio>11 #include<cstring>12 #include<iostream>13 using namespace std;14 #define inf 0x3f3f3f3f15  16 struct Edge{17     int to,nxt;18     Edge(int to=0,int nxt=0):19         to(to),nxt(nxt){}20 };21  22 const int maxn=1005;23  24 int n,cnt=0,ans=0,f[maxn],head[maxn];25 Edge E[maxn<<1];26  27 inline void a_ed(int from,int to){28     E[++cnt]=Edge(to,head[from]);  head[from]=cnt;29     E[++cnt]=Edge(from,head[to]);  head[to]=cnt;30 }31  32 void dfs(int no,int fa){33     int mx=-inf,mi=inf;34     for(int e=head[no];e;e=E[e].nxt){35         int nt=E[e].to;  if(nt==fa)  continue;36         dfs(nt,no);37         mx=max(mx,f[nt]);  mi=min(mi,f[nt]);38     }39     if(mx+mi<=3)  f[no]=mi+1;40     else  f[no]=mx+1;41     if(mx==-inf)  f[no]=3;42     if(f[no]==5){43         f[no]=0;44         ans++;45     }46     if(f[no]>=3&&fa==-1)  ans++;47 }48  49 int main(){50     scanf("%d",&n);51     for(int i=2,to;i<=n;i++){52         scanf("%d",&to);53         a_ed(i,to);54     }55     dfs(1,-1);56     printf("%d\n",ans);57     return 0;58 }

 

bzoj1217: [HNOI2003]消防局的设立 [树形dp]