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)