题目链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=106048#problem/B
题意:给出一些点相连,找出最小的点数覆盖所有的
用树形dp来解决
dp[i][0]表示i点不选,dp[i][1]表示i点选,dp[i][0] = sum{ dp[ son[i] ][1] }, // i不选,则i的子节点全选, dp[i][1] = sum { min( dp[ son[i] ][0], dp[ son[i] ][1] ) } + 1, i选的时候,子节点可选可不选,
在处理这题建立双向树,设dp[i][1] = 1;dp[i][0] = 0;
1 #include <iostream> 2 #include <cstdio> 3 #include <algorithm> 4 #include <cstring> 5 #include <vector> 6 using namespace std; 7 const int Max = 1500 + 10; 8 vector<int> son[Max]; 9 int dp[Max][2],n,vis[Max]; 10 void Input() 11 { 12 int root,cnt,s; 13 for(int i = 0; i < n; i++) 14 son[i].clear(); 15 for(int i = 0; i < n; i++) 16 { 17 scanf("%d:(%d)", &root, &cnt); 18 while(cnt--) 19 { 20 scanf("%d", &s); 21 son[root].push_back(s); 22 son[s].push_back(root); 23 } 24 } 25 } 26 void dfs(int root) 27 { 28 vis[root] = 1; 29 int len = (int) son[root].size(); 30 dp[root][1] = 1; 31 dp[root][0] = 0; 32 for(int i = 0; i < len; i++) 33 { 34 if(vis[ son[root][i] ]) 35 continue; 36 dfs(son[root][i]); 37 dp[root][1] += min(dp[ son[root][i] ][1], dp[ son[root][i] ][0]); 38 dp[root][0] += dp[ son[root][i] ][1]; 39 } 40 } 41 void solve() 42 { 43 memset(dp, 0, sizeof(dp)); 44 memset(vis, 0, sizeof(vis)); 45 dfs(0); 46 } 47 int main() 48 { 49 while(scanf("%d", &n) != EOF) 50 { 51 Input(); 52 solve(); 53 if(n == 0) 54 printf("0 "); 55 else 56 { 57 printf("%d ", min(dp[0][0], dp[0][1])); 58 } 59 60 } 61 return 0; 62 }