题意:给定一棵树,要选取最少的节点  使与 被选取的节点 相连的所有边  能够覆盖整棵树。

思路:DP,f[i][0]表示在不选取i号节点的情况下至少选多少个节点才能覆盖以i号节点为根的子树,f[i][1]表示在  选取  i号节点的情况下至少选多少个节点才能覆盖以i号节点为根的子树。

  转移方程:f[i][0]=∑f[son[i]][0],f[i][1]=∑min(f[son[i]][0],f[son[i]][1]);

  没什么细节。

 1 #include<iostream>
 2 #include<cstring>
 3 #include<string>
 4 #include<cstdio>
 5 #include<cstdlib>
 6 #include<cmath>
 7 #include<algorithm>
 8 #include<queue>
 9 #include<stack>
10 #include<set>
11 #include<map>
12 #include<vector>
13 #define ll long long
14 #define ull unsigned long long
15 using namespace std;
16 const int MAXN = 1505;
17 inline int read()
18 {
19     int x=0;char c=getchar();
20     for (;!isdigit(c);c=getchar());
21     for (;isdigit(c);c=getchar()) x=x*10+c-'0';
22     return x;
23 }
24 
25 inline void write(int x)
26 {
27     register int bit[20],i,p=0;
28     if (x==0) {putchar('0');return;}
29     for (;x;x/=10) bit[++p]=x%10;
30     for (i=p;i>0;--i) putchar(bit[i]+48);
31 }
32 int f[MAXN][2],bj[MAXN],n;
33 struct node{
34     int next,v;
35 }e[MAXN*2];int num=0,head[MAXN];
36 inline void add(int u,int v){
37     e[++num].next=head[u];
38     e[num].v=v;
39     head[u]=num;
40 }
41 void dfs(int x,int fa){
42     if(bj[x])return;
43     for(int i=head[x];i;i=e[i].next){
44         if(e[i].v==fa)continue;
45         dfs(e[i].v,x);
46         f[x][0]+=f[e[i].v][1];
47         f[x][1]+=min(f[e[i].v][0],f[e[i].v][1]);
48     }
49 }
50 int main()
51 {
52     cin>>n;
53     for(int i=0;i<n;i++)f[i][1]=1;
54     for(int i=1;i<=n;i++){
55         int x=read(),k=read();if(k==0)bj[x]=1;
56         for(int j=1;j<=k;j++){
57             int y=read();add(x,y),add(y,x);
58         }
59     }dfs(0,-1);
60     cout<<min(f[0][0],f[0][1]);
61     return 0;
62 }