1.题目描述:点击打开链接
2.解题思路:本题几乎就是树的最大独立集问题,只不过多了一个判断解的唯一性的要求。针对这种情况,可以做如下定义:
(1)d(u,0),f(u,0)分别表示以u为根的子树中,不选u点的最大人数和方案的唯一性(f=1表示唯一,f=0表示不唯一);
(2)d(u,1),f(u,1)分别表示以u为根的子树中,选u点的最大人数和方案的唯一性(f=1表示唯一,f=0表示不唯一);
相应的,状态转移方程也要有两种情况:
(1)d(u,1)的计算:由于选择了u,那么u的子结点都不能选。因此,d(u,1)=sum{d(v,0)|v是u的子结点}。当且仅当所有的f(v,0)=1时,f(u,1)才是1.
(2)d(u,0)的计算:因为u没有选,因此它的子结点可选可不选。因此,d(u,0)=sum{max(d(v,0),d(v,1))}。公式中先找到每个子结点的最大值,再求和。唯一性的判断:(i)如果d(v,0)==d(v,1),那么方案不唯一;(ii)如果max取到的那个结点的f=0,方案也不唯一。
3.代码:
#define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<algorithm> #include<string> #include<sstream> #include<set> #include<vector> #include<stack> #include<map> #include<queue> #include<deque> #include<cstdlib> #include<cstdio> #include<cstring> #include<cmath> #include<ctime> #include<functional> using namespace std; #define maxn 200+10 int d[maxn][2]; int f[maxn][2]; map<string, int>IDcache; vector<string>name; vector<int>boss[maxn]; int n; int ID(string s) { if (IDcache.count(s)) return IDcache[s]; name.push_back(s); return IDcache[s] = name.size() - 1; } int is_unique(int d1, int d2, int f1, int f2)//判断方案是否唯一 { if (d1 == d2)return 0; else return (d1 > d2) ? f1 : f2; } int dp(int id, int flag)//根据flag分类讨论 { int&ans = d[id][flag]; if (ans >= 0)return ans; ans = 0; if (flag) { if (boss[id].empty()){ f[id][flag] = 1; return ans = 1; } int k = boss[id].size(); int ok = 1; for (int i = 0; i < k; i++) { ans += dp(boss[id][i], 0); if (f[boss[id][i]][0] != 1) ok = 0; } ans++; if (ok)f[id][flag] = 1; else f[id][flag] = 0; } else { if (boss[id].empty()){ f[id][flag] = 1; return ans = 0; } int k = boss[id].size(); int ok = 1; for (int i = 0; i < k; i++) { int d1 = dp(boss[id][i], 0); int d2 = dp(boss[id][i], 1); int tmp = max(d1, d2); ans += tmp; if (!is_unique(d1, d2, f[boss[id][i]][0], f[boss[id][i]][1])) ok= 0; } if (ok)f[id][flag] = 1; else f[id][flag] = 0; } return ans; } int main() { //freopen("test.txt", "r", stdin); while (scanf("%d", &n)&& n) { name.clear(); IDcache.clear();//注意每次重新使用时清空name,IDcache memset(d, -1, sizeof(d)); memset(f, 0, sizeof(f)); memset(boss, 0, sizeof(boss)); string s, t; cin >> s; int id = ID(s); for (int i = 1; i < n; i++) { cin >> s >> t; int d1 = ID(s), d2 = ID(t); boss[d2].push_back(d1); } int ans, ff; int d1 = dp(id, 0); int d2 = dp(id, 1); ans = max(d1, d2); if (!is_unique(d1, d2, f[id][0], f[id][1])) ff = 0; else ff = 1; printf("%d %s\n", ans, ff ? "Yes" : "No"); } return 0; }
时间: 2024-12-06 04:06:20