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;
}