树形dp
题意:给你一颗树,在树的节点上面放上士兵,那么就可以覆盖与这个点相连的所有边,问使用最小的点覆盖所有的边。
dp[i][0] += dp[child][1];
dp[i][1] += min(dp[child][1],dp[child][0]);
注意:dp[i][1] + 1,表示对i这个点放一个士兵。
叶子节点dp[i][0] = 0; dp[i][1] = 1;
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
#define N 1502
int dp[N][2];
int father[N];
bool visit[N];
int n;
void dfs(int root) {
visit[root] = 1;
bool flag = 1;
for(int i = 0; i < n; i++) {
if(visit[i] == 0 && father[i] == root) {
//cout<<root<<' '<<i<<endl;
dfs(i);
flag = 0;
dp[root][0] += dp[i][1];
dp[root][1] += min(dp[i][0],dp[i][1]);
//cout<<root<<' '<<dp[root][0]<<' '<<dp[root][1]<<endl;
}
}
dp[root][1] += 1;
if(flag) {
dp[root][0] = 0;
dp[root][1] = 1;
}
}
int main() {
while(~scanf("%d",&n)) {
memset(visit,0,sizeof(visit));
memset(dp,0,sizeof(dp));
memset(father,0,sizeof(father));
int index , m;
int root = -1;bool flag = 0;
for(int i = 0; i < n; i++) {
scanf("%d:(%d)",&index,&m);
int x;
for(int j = 1; j <= m; j++) {
scanf("%d",&x);
father[x] = index;
if(flag == 0 || root == x) {
flag = 1;
root = index;
}
}
}
dfs(root);
printf("%d\n",min(dp[root][0],dp[root][1]));
}
return 0;
}