UVa 1220 (树的最大独立集) Party at Hali-Bula

题意:

有一棵树,选出尽可能多的节点是的两两节点不相邻,即每个节点和他的子节点只能选一个。求符合方案的最大节点数,并最优方案判断是否唯一。

分析:

d(u, 0)表示以u为根的子树中,不选u节点能得到的最大人数,f(u, 0)表示方案是否唯一。

d(u, 1)表示选u节点能得到的最大人数,同理,f(u, 1)表示方案是否唯一。

状态的转移:

    • d(u, 1)的计算:因为选了u节点,所以u的子节点都不能选。d(u, 1) = sum{ d(v, 0) | v是u的子节点 }
    • f(u, 1)的计算:当且仅当f(v, 0) == 1时,f(u, 1)才是1
  •  
    • d(u, 0)的计算:因为没有选u节点,所以对于每个子节点v可选可不选。d(u, 0) = sum{ max(d(v, 0),  d(v, 1)) }
    • f(u, 0)的计算:方案不唯一有两种情况,某个d(v, 1) == d(v, 0) 或者 对应取到max方案的f为1

这里用了C++中的map,将字符串与编号对应起来,编写代码比较方便。

 

 1 //#define LOCAL
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <string>
 6 #include <map>
 7 #include <vector>
 8 #include <iostream>
 9 using namespace std;
10 
11 const int maxn = 205;
12 vector<int> sons[maxn];
13 map<string, int> dict;
14 int cnt, d[maxn][2], f[maxn][2];
15 
16 int ID(const string& s)
17 {
18     if(!dict.count(s))    dict[s] = cnt++;
19     return dict[s];
20 }
21 
22 int dp(int u, int k) {
23   f[u][k] = 1;
24   d[u][k] = k;
25   for(int i = 0; i < sons[u].size(); i++) {
26     int v = sons[u][i];
27     if(k == 1) {  //选节点u
28       d[u][1] += dp(v, 0);
29       if(!f[v][0]) f[u][1] = 0; //如果子节点v不唯一,则父节点u也不唯一
30     } else {
31       d[u][0] += max(dp(v, 0), dp(v, 1));
32       if(d[v][0] == d[v][1]) f[u][k] = 0;
33       else if(d[v][0] > d[v][1] && !f[v][0]) f[u][k] = 0;
34       else if(d[v][1] > d[v][0] && !f[v][1]) f[u][k] = 0;
35     }
36   }
37   return d[u][k];
38 }
39 
40 int main(void)
41 {
42     #ifdef    LOCAL
43         freopen("1220in.txt", "r", stdin);
44     #endif
45     
46     int n;
47     string s, s2;
48     while(cin >> n >> s)
49     {
50         getchar();
51         cnt = 0;
52         dict.clear();
53         for(int i = 0; i <= n; ++i)    sons[i].clear();
54 
55         //cin >> s;
56         ID(s);
57         for(int i = 1; i < n; ++i)
58         {
59             cin >> s >> s2;
60             sons[ID(s2)].push_back(ID(s));
61         }
62         printf("%d ", max(dp(0, 0), dp(0, 1)) );
63         bool unique = false;
64         if(d[0][0] > d[0][1] && f[0][0])    unique = true;
65         if(d[0][1] > d[0][0] && f[0][1])    unique = true;
66         printf("%s\n", unique ? "Yes" : "No");
67     }
68 
69     return 0;
70 }
代码君

 

posted @ 2014-10-07 22:52  AOQNRMGYXLMV  阅读(413)  评论(0编辑  收藏  举报