首页 > 代码库 > UVa 1220 Hali-Bula的晚会(树的最大独立集)

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         //树形的DFS35         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的晚会(树的最大独立集)