题目
最少安排多少士兵使士兵能瞭望所有的路(在一棵树上)
分析
用树形dp,
f
[
x
]
[
0
]
表
示
在
点
x
不
放
士
兵
的
最
少
安
排
数
,
f
[
x
]
[
1
]
表
示
放
士
兵
的
最
少
安
排
数
(
初
始
值
为
1
)
f[x][0]表示在点x不放士兵的最少安排数,f[x][1]表示放士兵的最少安排数(初始值为1)
f[x][0]表示在点x不放士兵的最少安排数,f[x][1]表示放士兵的最少安排数(初始值为1)
明
显
可
得
f
[
x
]
[
0
]
+
=
f
[
s
o
n
]
[
1
]
;
f
[
x
]
[
1
]
+
=
m
i
n
(
f
[
s
o
n
]
[
0
]
,
f
[
s
o
n
]
[
1
]
)
;
明显可得f[x][0]+=f[son][1];f[x][1]+=min(f[son][0],f[son][1]);
明显可得f[x][0]+=f[son][1];f[x][1]+=min(f[son][0],f[son][1]);
最
后
输
出
m
i
n
(
f
[
r
o
o
t
]
[
0
]
,
f
[
r
o
o
t
]
[
1
]
)
最后输出min(f[root][0],f[root][1])
最后输出min(f[root][0],f[root][1])
代码
#include <cstdio>
#include <cctype>
using namespace std;
struct node{int y,next;}e[15001]; int ls[1501]; bool v[1501];
int n,k,f[1501][2],m,root,x,y;
int in(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
int min(int a,int b){return (a<b)?a:b;}
void dp(int x){
if (!ls[x]) return;
for (int i=ls[x];i;i=e[i].next){
dp(e[i].y);
f[x][0]+=f[e[i].y][1];
f[x][1]+=min(f[e[i].y][0],f[e[i].y][1]);
}
}
int main(){
n=in();
for (int i=1;i<=n;i++){
x=in()+1; k=in(); f[i][1]=1;
while (k--) e[++m]=(node){y=in()+1,ls[x]},ls[x]=m,v[y]=1;
}
for (root=1;root<=n&&v[root];root++);
dp(root); return !printf("%d",min(f[root][0],f[root][1]));
}