解题思路:此题是典型的树形dp中最大独立集的问题。定义两个数组s[u]和gs[u],分别代表选择u时只能选孙节点gs[u]和不选择u时选择其儿子的最大值。这里使用刷表的方法,随时更新s[u]和gs[u]两个数组。因为需要判断是否唯一,因而定义了三个数组,分别对应选子节点和孙节点是否唯一以及判断子节点和孙节点大小并选择后最终的本节点是否唯一。
题目大意:一个公司员工要举行聚会,要求任意一个人不能和他的直接上司同时到场,一个员工只有一个支系上司,现在求最多有多少人到场,并且方案是否唯一。
Sample Input
6
Jason
Jack Jason
Joe Jack
Jill Jason
John Jack
Jim Jill
2
Ming
Cho Ming
0
Sample Output
4 Yes
1 No
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
#include<string>
#include<vector>
using namespace std;
int n,s[201],gs[201],sf[201],gf[201],f[201];
map<string,int> Q1;
map<int,string> Q2;
vector<int> Q[201];
int dfs(int u,int fa)
{
if(Q[u].empty()) return 1;
for(int i=0;i<Q[u].size();i++)
{
if(Q[u][i]!=fa) //父节点对应的不是子树
{
s[u]+=dfs(Q[u][i],u);
if(f[Q[u][i]]==1) sf[u]=1; //若有子节点不唯一,则待选择的子节点最大不唯一
}
if(fa!=-1)
{
gs[fa]+=dfs(Q[u][i],u);
if(f[Q[u][i]]==1) gf[fa]=1; //有孙节点不唯一,则对应的节点待选择孙节点最大不唯一
}
}
if(s[u]==gs[u]+1) { //孙与子节点最大相等,则本节点不唯一
f[u]=1;
return s[u];
}
int ans;
if(s[u]>gs[u]) //选择子节点
{
f[u]=sf[u];
ans=s[u];
}
else //选择孙节点
{
f[u]=gf[u];
ans=gs[u];
}
return ans;
}
int main()
{
while(cin>>n)
{
if(n==0) break;
int count=2;
Q1.clear();Q2.clear();
for(int i=1;i<=n;i++) Q[i].clear();
memset(s,0,sizeof(s));memset(gs,0,sizeof(gs));
memset(sf,0,sizeof(sf));memset(gf,0,sizeof(gf));
memset(f,0,sizeof(f));
string s;cin>>s;Q1[s]=1;Q2[1]=s;
for(int i=2;i<=n;i++)
{
string s1,s2;
cin>>s1>>s2;
if(Q1.count(s1)==0) {
Q1[s1]=count;
Q2[count++]=s1;
}
Q[Q1[s2]].push_back(count-1);
}
cout<<dfs(1,-1)<<" ";
if(f[1]==1) cout<<"NO"<<endl;
else cout<<"YES"<<endl;
}
return 0;
}