有两种做法:一种是经典二分图最小顶点覆盖,一种是树形DP,我用的后者。
第一次学习树形DP……
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <vector> 5 #include <algorithm> 6 7 using namespace std; 8 9 const int MAXN = 1600; 10 11 int N, root; 12 int dp[MAXN][2]; 13 vector<int> tree[MAXN]; 14 15 void init() 16 { 17 root = -1; 18 19 for ( int i = 0; i < N; ++i ) 20 { 21 int u, cnt; 22 tree[i].clear(); 23 scanf("%d:(%d)", &u, &cnt ); 24 if ( root == -1 ) root = u; 25 for ( int j = 0; j < cnt; ++j ) 26 { 27 int v; 28 scanf( "%d", &v ); 29 tree[u].push_back(v); 30 } 31 } 32 return; 33 } 34 35 int DFS( int fa ) 36 { 37 dp[fa][0] = 0; 38 dp[fa][1] = 1; 39 int len = tree[fa].size(); 40 for ( int i = 0; i < len; ++i ) 41 { 42 int v = tree[fa][i]; 43 DFS( v ); 44 dp[fa][0] += dp[v][1]; 45 dp[fa][1] += min( dp[v][0], dp[v][1] ); 46 } 47 return min( dp[fa][0], dp[fa][1] ); 48 } 49 50 int main() 51 { 52 while ( scanf( "%d", &N ) == 1 ) 53 { 54 init(); 55 printf( "%d\n", DFS(root) ); 56 } 57 return 0; 58 }