一道细节满满的题,找了一晚上错终于AC了
本题几乎就是树的最大独立子集问题,但是多了一个要求,判断唯一性。
那么如何判断唯一性呢,这个唯一性充满了细节。
1.如果两个情况相等:
如果选了或者不选以该结点为根的子树,得到的结果一样,那么一定不唯一。
2.如果一种情况大于另一种情况:
如果以该节点为根的子树大于不以该节点为根的子树,我们要判断一下是否以该节点为根的子树是唯一的,
如果不是,那么这种情况也不唯一。
反过来同理。
强烈建议自己实现一遍,这会让你对独立子集问题有更深刻的理解。
#include<bits/stdc++.h>
using namespace std;
map<string,int> m;
vector<int> g[205];
int d[205][2];
int f[205][2];
int dfs(int u,int flag){
if(d[u][flag])
return d[u][flag];
if(flag) d[u][flag]=1;
for(int i=0;i<g[u].size();i++){
int v=g[u][i];
if(flag){
d[u][flag]+=dfs(v,flag^1);
f[u][flag]=f[v][flag^1];
}
else{
if(dfs(v,flag)==dfs(v,flag^1))
{
f[u][flag]=0;
f[u][flag^1]=0;
d[u][flag]+=dfs(v,flag);
}
else{
if(dfs(v,flag)>dfs(v,flag^1) ){
if(f[v][flag]==0){
f[u][flag]=0;
}
d[u][flag]+=dfs(v,flag);
}
else if(dfs(v,flag^1)>dfs(v,flag) ){
if( f[v][flag^1]==0){
f[u][flag]=0;
}
d[u][flag]+=dfs(v,flag^1);
}
}
}
}
return d[u][flag];
}
void print(){
if(d[0][1]>d[0][0]){
printf("%d ",d[0][1]);
if(f[0][1]){
printf("Yes\n");
}else{
printf("No\n");
}
}
if(d[0][1]<d[0][0]){
printf("%d ",d[0][0]);
if(f[0][0]){
printf("Yes\n");
}else{
printf("No\n");
}
}
if(d[0][1]==d[0][0]){
printf("%d ",d[0][0]);
printf("No\n");
}
}
int main(){
int n;
while(scanf("%d",&n) && n){
memset(d,0,sizeof(d));
memset(f,0,sizeof(f));
for(int i=0;i<205;i++)
g[i].clear();
int tail=0;
string str1,str2;
cin>>str1;
m.clear();
m[str1]=tail++;
for(int i=0;i<n-1;i++){
cin>>str1;
cin>>str2;
if(m.find(str1)==m.end())
m[str1]=tail++;
if(m.find(str2)==m.end())
m[str2]=tail++;
g[m[str2]].push_back(m[str1]);
}
for(int i=0;i<=n;i++){
f[i][1]=1;
f[i][0]=1;
}
int a2=dfs(0,0);
int a1=dfs(0,1);
print();
}
}