文章目录
消防局的设立
题目:
-
2020
2020
2020 年,人类在火星上建立了一个庞大的基地群,总共有
n
n
n 个基地,编号
1
∼
n
1∼n
1∼n。
起初为了节约材料,人类只修建了 n − 1 n−1 n−1 条道路来连接这些基地,并且每两个基地都能够通过道路到达,所以所有的基地形成了一个巨大的树状结构。
如果基地 A A A 到基地 B B B 至少要经过 d d d 条道路的话,我们称基地 A A A 到基地 B B B 的距离为 d d d。
由于火星上非常干燥,经常引发火灾,人类决定在火星上修建若干个消防局。
消防局只能修建在基地里,每个消防局有能力扑灭与它距离不超过 2 2 2 的基地的火灾。
你的任务是计算至少要修建多少个消防局才能够确保火星上所有的基地在发生火灾时,消防队有能力及时扑灭火灾。
数据范围
1≤n≤1000
dp方程式:
- f [ u ] [ 0 ] : f[u][0] : f[u][0]: 表示u的子树满足且向上的父亲的父亲满足。
- f [ u ] [ 1 ] : f[u][1] : f[u][1]: 表示u的子树满足且向上的父亲满足。
- f [ u ] [ 2 ] : f[u][2] : f[u][2]: 表示u的所有的子树满足。
- f [ u ] [ 3 ] : f[u][3] : f[u][3]: 表示u的所有儿子的子树满足。
- f [ u ] [ 4 ] : f[u][4] : f[u][4]: 表示u的所有儿子的儿子的子树满足。
状态转移:
- f [ u ] [ 0 ] = 1 + ∑ f[u][0] = 1 + ∑ f[u][0]=1+∑v f [ v ] [ 1 ] f[v][1] f[v][1]
- f [ u ] [ 1 ] = m i n ( f [ v ] [ 0 ] + ∑ f [ v ′ ] [ 3 ] ) f[u][1] = min(f[v][0] + ∑f[v'][3]) f[u][1]=min(f[v][0]+∑f[v′][3])
- f [ u ] [ 2 ] = m i n ( f [ v ] [ 1 ] + ∑ f [ v ′ ] [ 2 ] ) f[u][2] = min(f[v][1] + ∑f[v'][2]) f[u][2]=min(f[v][1]+∑f[v′][2])
- f [ u ] [ 3 ] = ∑ f [ v ] [ 2 ] f[u][3] = ∑f[v][2] f[u][3]=∑f[v][2]
- f [ u ] [ 4 ] = ∑ f [ v ] [ 3 ] f[u][4] = ∑f[v][3] f[u][4]=∑f[v][3]
最后dp更新,上层满足的下层也满足。
- f [ u ] [ 1 ] = m i n ( f [ u ] [ 1 ] , f [ u ] [ 0 ] ) ; f[u][1] = min(f[u][1],f[u][0]); f[u][1]=min(f[u][1],f[u][0]);
- f [ u ] [ 2 ] = m i n ( f [ u ] [ 2 ] , f [ u ] [ 1 ] ) ; f[u][2] = min(f[u][2],f[u][1]); f[u][2]=min(f[u][2],f[u][1]);
- f [ u ] [ 3 ] = m i n ( f [ u ] [ 3 ] , f [ u ] [ 2 ] ) ; f[u][3] = min(f[u][3],f[u][2]); f[u][3]=min(f[u][3],f[u][2]);
- f [ u ] [ 4 ] = m i n ( f [ u ] [ 4 ] , f [ u ] [ 3 ] ) ; f[u][4] = min(f[u][4],f[u][3]); f[u][4]=min(f[u][4],f[u][3]);
代码
#include<iostream>
#include<cstring>
using namespace std;
const int N = 1100;
int f[N][6];
int h[N],e[N<<1],ne[N<<1],idx;
void add(int a,int b){
ne[idx] = h[a],e[idx] = b,h[a] = idx++;
}
int n,tp;
//f[u][0] = 1 + sum:f[v][4];
//f[u][1] = min(f[v][0] + sum:f[v'][3]);
//f[u][2] = min(f[v][1] + sum:f[v'][2]);
//f[u][3] = sum:f[v][2];
//f[u][4] = sum:f[v][3];
void dfs(int u,int fa){
bool leaf = 1;
int sum1,sum2,sum3;
sum1 = sum2 = sum3 = 0;
for(int i = h[u];~i;i=ne[i]){
int y = e[i];
if(y == fa)continue;
leaf = 0;
dfs(y,u);
sum1 += f[y][4];
sum2 += f[y][3];
sum3 += f[y][2];
}
if(leaf){f[u][0] = f[u][1] = f[u][2] = 1;return ;}
int mn1=0x3f3f,mn2=0x3f3f;
for(int i = h[u];~i;i=ne[i]){
int y = e[i];
if(y == fa)continue;
mn1 = min(mn1,f[y][0] + sum2 - f[y][3]);
mn2 = min(mn2,f[y][1] + sum3 - f[y][2]);
}
f[u][0] = 1 + sum1;
f[u][1] = mn1;
f[u][2] = mn2;
f[u][3] = sum3;
f[u][4] = sum2;
f[u][1] = min(f[u][1],f[u][0]);
f[u][2] = min(f[u][2],f[u][1]);
f[u][3] = min(f[u][3],f[u][2]);
f[u][4] = min(f[u][4],f[u][3]);
}
int main(){
cin >> n;
memset(h,-1,sizeof h);
for(int i = 2;i<=n;i++){
cin >> tp;
add(i,tp);
add(tp,i);
}
dfs(1,-1);
cout << f[1][2] << endl;
return 0;
}