分析明天在写,先睡觉!
【key】
建树vector<int>child[N] (类似于邻接矩阵存储图)
上下级关系决定有向图
字典树用map容器作映射解决
动态规划递推关系:
dp[u][1]+=dp[child[u][i]][0];
dp[u][0]+=max(dp[child[u][i]][1],dp[child[u][i]][0]);
唯一性判定有点难!
也用二维数组递推关系解决:
1.不取当前节点的唯一性取决于你要选取那个子节点的唯一性以及是否选取他,根本上取决于动态数组dp的表达式关系;
if(dp[child[u][i]][1]==dp[child[u][i]][0]) f[u][0]=0;
else if(dp[child[u][i]][0]>dp[child[u][i]][1]&&f[child[u][i]][0]==0) f[u][0]=0;
else if(dp[child[u][i]][0]<dp[child[u][i]][1]&&f[child[u][i]][1]==0) f[u][0]=0;
2.取当前节点u的唯一性取决于是否存在子节点不唯一,有一个子节点不唯一,该节点取1的状态就为0(0表示不唯一,1唯一)
if(f[child[u][i]][0]==0) f[u][1]=0;
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <climits>
#include <map>
#include <vector>
#include <list>
#include <stack>
#include <queue>
#define eps 1e-9
#define pi acos(-1)
#define clr(k,v) memset(k,v,sizeof(k));
using namespace std;
typedef long long ll;
const int maxn=410;
const int mod=1000000009;
const int SZ = 1<<20;/*
struct fastio{
char inbuf[SZ];char outbuf[SZ];fastio(){//¸ßËÙ»º´æ
setvbuf(stdin,inbuf,_IOFBF,SZ);
setvbuf(stdout,outbuf,_IOFBF,SZ);
}}io;*/
vector<int>child[maxn];
map<string,int>mp;//做一个string->int的映射,方便建立child[]
int dp[maxn][2];//dp[i][0]不包含编号为i的子树最大集合,dp[i][1]包含i的子树最大集合
bool f[maxn][2];//唯一性判断,也具有树节点关联性,f[i][]==1子树唯一,0有多条
void dfs(int u){
int size=child[u].size();
if(size==0){
dp[u][0]=0;
dp[u][1]=1;
return;//递归基
}
for(int i=0;i<size;++i){
dfs(child[u][i]);//遍历完第i个节点后才能处理该节点的dp值
dp[u][1]+=dp[child[u][i]][0];
dp[u][0]+=max(dp[child[u][i]][1],dp[child[u][i]][0]);
if(dp[child[u][i]][1]==dp[child[u][i]][0]) f[u][0]=0;
else if(dp[child[u][i]][0]>dp[child[u][i]][1]&&f[child[u][i]][0]==0) f[u][0]=0;
else if(dp[child[u][i]][0]<dp[child[u][i]][1]&&f[child[u][i]][1]==0) f[u][0]=0;
if(f[child[u][i]][0]==0) f[u][1]=0;
}
dp[u][1]++;//可以提前初始化,也可放在这里
}
int main()
{
// freopen("input.txt","r",stdin);
int n;
while(cin>>n&&n){
clr(dp,0);
clr(f,1);//初始化都唯一
int top=1;
string str1,str2;
cin>>str1;
mp[str1]=top++;
for(int i=1;i<n;i++){
cin>>str1>>str2;
if(!mp[str1]) mp[str1]=top++;
if(!mp[str2]) mp[str2]=top++;//做一个mp表格
child[mp[str2]].push_back(mp[str1]);
}
dfs(1);
for(int i=1;i<=n;i++) child[i].clear();
mp.clear();
bool ok=true;
if(dp[1][1]>dp[1][0]) ok=f[1][1];
else if(dp[1][1]<dp[1][0]) ok=f[1][0];
else ok=false;
printf("%d ",max(dp[1][0],dp[1][1]));//dp[i][0]不包含编号为i的子树最大集合,dp[i][1]包含i的子树最大集合
puts(ok?"Yes":"No");
}
return 0;
}