UVa 1220 Hali-Bula的晚会(树的最大独立集)

Posted 谦谦君子,陌上其华

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UVa 1220 Hali-Bula的晚会(树的最大独立集)相关的知识,希望对你有一定的参考价值。

https://vjudge.net/problem/UVA-1220

题意:

公司里有n个人形成一个树状结构,即除了老板以外每个员工都有唯一的直属上司。要求选尽量多的人,但不能同时选择一个人和他的直属上司。输出最多能选多少人并判断是否唯一。

 

思路:

树的最大独立集问题。就是需要额外判定是否是唯一的。

因为输入的都是人名,所以首先就是用map容器来处理,上下属的关系就用vector容器来处理。

d[u][1]表示以u为根的子树中,选u点能得到的最大人数,f[u][1]判断这种方案是否唯一。

d[u][0]表示以u为根的子树中,不选u点能得到的最大人数,f[u][0]判断这种方案是否唯一。

状态转移方程其实不是很难。首先分析d[u][1],因为u选了,所以u的子结点都不能选,它的子节点的状态只能是这样的,所以此时d[u][1]=sum(d[v][0]|v是u的子节点)。容易想到f[v][0]都为唯一时,f[u][1]才是唯一的。

其次是d[u][0],此时u的子节点可选可不选,所以我们需要挑选出更大的那个,每个子节点都是这样处理,最后像上面那样加起来就可以了。转移方程就是d[u][0]=sum(max(d[v][0],d[v][1]))。方案唯一值的判定和上面是一样的,就是分析你所挑选的更大的那个。

根结点值依赖于子节点,所以需要用DFS来处理

 1 #include<iostream> 
 2 #include<string>
 3 #include<cstring>
 4 #include<vector>
 5 #include<algorithm>
 6 #include<map>
 7 using namespace std;
 8 
 9 const int maxn = 200+5;
10 
11 int n, cnt;
12 string s1, s2;
13 
14 int d[maxn][2], f[maxn][2];
15 
16 map<string, int> id;
17 vector<int> sons[maxn];
18 
19 
20 void solve(int u)
21 {
22     //最下属的只有两种情况
23     if (sons[u].size() == 0)
24     {
25         d[u][0] = 0;
26         d[u][1] = 1;
27         return;
28     }
29     int k = sons[u].size();
30 
31     for (int i = 0; i < k; i++)
32     {
33         int son = sons[u][i];
34         //树形的DFS
35         solve(son);
36         d[u][1] += d[son][0];
37         //一旦有子节点不唯一,它也不唯一
38         if (!f[son][0])    f[u][1] = 0;
39         //u不选时,它的子节点可选可不选,此时需要选个大的
40         d[u][0] += max(d[son][1], d[son][0]);  
41 
42         //判断是否唯一
43         if (d[son][0]>d[son][1] && !f[son][0])             f[u][0] = 0;
44         else if (d[son][1] > d[son][0] && !f[son][1] )     f[u][0] = 0;
45         else if (d[son][0] == d[son][1])                   f[u][0] = 0;
46 
47     }
48     ++d[u][1];
49 }
50 
51 int main()
52 {
53     //freopen("D:\\txt.txt", "r", stdin);
54     while (cin >> n && n)
55     {
56         memset(d, 0, sizeof(d));
57         //初始化都为唯一
58         for (int i = 0; i <= n; i++)
59             f[i][1] = f[i][0] = 1;
60         id.clear();
61         for (int i = 1; i <= n; i++)
62             sons[i].clear();
63         cnt = 0;
64 
65         cin >> s1;
66         id[s1] = ++cnt;
67         for (int i = 1; i < n; i++)
68         {
69             cin >> s1 >> s2;
70             if (!id[s1])  id[s1] = ++cnt;
71             if (!id[s2])  id[s2] = ++cnt;
72             sons[id[s2]].push_back(id[s1]);
73          }
74 
75         solve(1);
76 
77         if (d[1][0] == d[1][1])  printf("%d No\n", d[1][0]);
78         else if (d[1][0] > d[1][1])  printf("%d %s\n", d[1][0], !f[1][0] ? "No" : "Yes");
79         else  printf("%d %s\n", d[1][1], !f[1][1] ? "No" : "Yes");
80     }
81     return 0;
82 }

 

以上是关于UVa 1220 Hali-Bula的晚会(树的最大独立集)的主要内容,如果未能解决你的问题,请参考以下文章

Party at Hali-Bula UVA - 1220 (树形dp)

UVa 1220 - Party at Hali-Bula(树形DP)

UVA-1220-Party at Hali-Bula && UVA-1218-Perfect Service(树形DP)

UVA-01220 Party at Hali-Bula (树形DP+map)

Party at Hali-Bula(树形DP+判断方案数是否唯一)

树的最大独立集