Strategic game UVA - 1292

树的最大独立集:对于一颗n个结点的无根树,选出尽量多的结点,使得任何两个结点都不相邻。

题解:dp[ i ][ 0 ~ 1 ]表示以 i 为根结点的子树的最大独立集,0表示不选 i ,1表示选 i 。记 i 的儿子为son。

选 i 的话,其儿子可选可不选,即dp[ i ][ 1 ]+=min(dp[ son ][ 0 ],dp[ son ][ 1 ]);不选 i 的话,就必须选 i 的儿子,即dp[ i ][ 0 ]+=dp[ son ][ 1 ]。

 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<vector>
 6 #define mem(array) memset(array,0,sizeof(array))
 7 using namespace std;
 8 
 9 int n,dp[1600][2];
10 bool vis[1600];
11 vector<int> G[1600];
12 
13 void Read(){
14     for(int i=0;i<n;i++) G[i].clear(); 
15     for(int i=0;i<n;i++){
16         int a,b,c;
17         scanf("%d:(%d)",&a,&b);
18         for(int j=0;j<b;j++){
19             scanf("%d",&c);
20             G[a].push_back(c);
21             G[c].push_back(a);
22         }
23     }    
24 }
25 
26 void DFS(int root){
27     dp[root][1]=1;
28     dp[root][0]=0;
29     vis[root]=true;
30     
31     for(int i=0;i<G[root].size();i++){
32         int sons=G[root][i];
33         if(vis[sons]) continue;
34 
35         DFS(sons);
36         dp[root][0]+=dp[sons][1];
37         dp[root][1]+=min(dp[sons][1],dp[sons][0]);
38     }
39 }
40 
41 int main()
42 {   while(~scanf("%d",&n)){
43         Read();
44         mem(vis);mem(dp);
45         DFS(0);
46         cout<<min(dp[0][1],dp[0][0])<<endl;
47     }
48     return 0;
49 } 

 

posted @ 2017-09-05 17:15  天之道,利而不害  阅读(161)  评论(0编辑  收藏  举报