PS:很久没写博客了,更几篇。
按紫书上思路写的,按自己思路写错好几次啊啊啊。
dp(u,0)代表选u,dp(u,1) 代表不选u,函数返回值pair的first代表能选到的最多的人,second 代表解是否唯一,当second为1时唯一,second为0时不唯一。
感觉我这份代码重复计算有点多,可以用数组来保存状态以减少重复计算。
具体实现及思路见代码注释。
#include<bits/stdc++.h>
using namespace std;
#define pa pair<int,int>
unordered_map<string,int> id; ///将名字映射为id
vector<int> son[222]; ///保存子节点数据
pa dp(int u,int c){
int d=0,f=1; ///d为被选择的人数
if(son[u].empty()){ ///u没有子节点。
d=(c==1)?1:0; ///当选择u时d为1,否则为0
return make_pair(d,1);
}
pa a,b;
if(c==1){ ///选择u时,u的子节点都不可以选。d+=dp(v,0)
for(int i=0;i<son[u].size();i++){
a=dp(son[u][i],0);
if(a.second==0) f=0; ///当不选子节点的方案不唯一时,此方案也不唯一
d+=a.first;
}
d++; ///u被选择,所以总人数要加一
return make_pair(d,f);
}
else{ ///不选u时,d+=max(dp(v,0),dp(v,1));
for(int i=0;i<son[u].size();i++){
a=dp(son[u][i],0);
b=dp(son[u][i],1);
if(a.first==b.first) f=0; ///判断方案的唯一性
else if(a.first>b.first&&a.second==0) f=0;
else if(a.first<b.first&&b.second==0) f=0;
d+=max(a.first,b.first);
}
return make_pair(d,f);
}
}
int main(){
int n;
string a,b;
while(cin>>n&&n){
id.clear();
int cnt=1;
cin>>a;
id[a]=0;
for(int i=0;i<=n;i++) son[i].clear();
for(int i=1;i<n;i++){
cin>>a>>b;
if(!id.count(a)) id[a]=cnt++;
if(!id.count(b)) id[b]=cnt++;
son[id[b]].push_back(id[a]);
}
int ans,f;
pa c=dp(0,1),d=dp(0,0);
if(c.first>d.first) f=c.second,ans=c.first;
else if(c.first<d.first) f=d.second,ans=d.first;
else f=0,ans=c.first;
a=(f==1)?" Yes\n":" No\n";
cout<<ans<<a;
}
return 0;
}