鲍勃喜欢玩电脑游戏,特别是战略游戏,但有时他找不到解决问题的方法,这让他很伤心。
现在他有以下问题。
他必须保护一座中世纪城市,这条城市的道路构成了一棵树。
他必须在节点上放置最少数量的士兵,以便他们可以观察到所有的边。
你能帮助他吗?
例如,下面的树:
只需要放置1名士兵(在节点1处),就可观察到所有的边。
输入格式
输入包含多组测试数据,每组测试数据用以描述一棵树。
对于每组测试数据,第一行包含整数N,表示树的节点数目。
接下来N行,每行按如下方法描述一个节点。
节点编号:(子节点数目) 子节点 子节点 …
节点编号从0开始,每个节点的子节点数量均不超过10,每个边在输入数据中只出现一次。
输出格式
对于每组测试数据,输出一个占据一行的结果,表示最少需要的士兵数。
数据范围
0<N≤1500
输入样例:
4
0:(1) 1
1:(2) 2 3
2:(0)
3:(0)
5
3:(3) 1 4 2
1:(1) 0
2:(0)
0:(0)
4:(0)
输出样例:
1
2
首先找到这个有根树的根。
设计状态
f[u][0]表示这个节点不选
f[u][1]表示这个节点选
转移
f
[
u
]
[
0
]
=
f
[
u
]
[
0
]
+
f
[
v
]
[
1
]
;
f[u][0]=f[u][0]+f[v][1];
f[u][0]=f[u][0]+f[v][1];
f
[
u
]
[
1
]
=
f
[
u
]
[
1
]
+
m
i
n
(
f
[
v
]
[
0
]
+
f
[
v
]
[
1
]
)
;
f[u][1]=f[u][1]+min(f[v][0]+f[v][1]);
f[u][1]=f[u][1]+min(f[v][0]+f[v][1]);
#include<bits/stdc++.h>
#define maxn 4000
using namespace std;
int n;
int cnt;
int head[maxn];
struct node{
int to;
int next;
}e[maxn];
void add(int u,int v){
e[++cnt].to=v;
e[cnt].next=head[u];
head[u]=cnt;
}
int f[maxn][3];
int du[maxn];
void dfs(int u){
f[u][1]=1;
f[u][0]=0;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
dfs(v);
f[u][1]+=min(f[v][1],f[v][0]);
f[u][0]+=f[v][1];
}
}
int main(){
while(scanf("%d",&n)!=EOF){
memset(head,0,sizeof(head));
cnt=0;
memset(du,0,sizeof(du));
memset(f,0,sizeof(f));
for(int i=1;i<=n;i++){
int x;
int size;
char cc;
scanf("%d",&x);
cin>>cc;
cin>>cc;
scanf("%d",&size);
cin>>cc;
int y;
for(int i=1;i<=size;i++){
scanf("%d",&y);
add(x,y);
du[y]++;
}
}
int pos;
for(int i=0;i<n;i++){
if(!du[i]){
pos=i;
break;
}
}
dfs(pos);
printf("%d\n",min(f[pos][1],f[pos][0]));
}
}