首页 > 代码库 > 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的晚会(树的最大独立集)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。