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 }
代码君

 

你可能感兴趣的:(part)