链接:https://vjudge.net/contest/204190#problem/B
题意:给定一棵关系树 , 从中选择一些点 , 使这些点均不存在亲子关系 , 最多能取多少个点 , 并且判断取法是否唯一 .

分析: 树形dp
首先一次dfs 求出最大独立集
用boss[i]存储编号i 的上司。
假设上司i的下属为j
如果最大独立集不唯一时,必定有dp[i][0] > dp[i][1] 且 dp[j][0] == dp[j][1];
否则唯一

代码:

#include <bits/stdc++.h>
using namespace std;
#define mem(a,n) memset(a,n,sizeof(a))
#define rep(i,a,n) for(int i=a;i<n;i++)
#define pb push_back
#define IO ios::sync_with_stdio(false)
#define fre freopen("in.txt","r",stdin)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef long long ll;
const double PI=acos(-1.0);
const double eps=1e-8;
const int INF=0x3f3f3f3f;
const int MOD=1e9+7;
const int N=2e2+5;
const int dir[4][2]= {-1,0,1,0,0,-1,0,1};
string s1,s2;
map<string,int>mp;
int n,dp[N][2],boss[N];
int vis[N];
void dfs(int u)///最大独立集
{
    vis[u]=1;
    dp[u][1]=1;
    rep(i,1,n+1)
    {
        if(boss[i]==u&&!vis[i])
        {
            dfs(i);
            dp[u][1]+=dp[i][0];
            dp[u][0]+=max(dp[i][0],dp[i][1]);
        }
    }
}
bool check()
{
    rep(i,1,n+1)
    {
        if(dp[i][0] > dp[i][1])
            rep(j,1,n+1)
            if(boss[j]==i && dp[j][0] == dp[j][1])///有多解时必有某一子节点i dp[j][0]==dp[j][1]
                return 1;
    }
    return 0;
}
void init()
{
    mp.clear();
    mem(vis,0);
    mem(boss,0);
    mem(dp,0);
}
int main()
{
    //fre;
    IO;
    while(cin>>n&&n)
    {
        cin>>s1;
        mp[s1]=1;
        boss[mp[s1]]=1;
        int cnt=2;
        rep(i,1,n)
        {
            cin>>s1>>s2;
            if(!mp[s1]) mp[s1]=cnt++;
            if(!mp[s2]) mp[s2]=cnt++;
            boss[mp[s1]]=mp[s2];
        }
        dfs(1);
        int maxx=max(dp[1][0],dp[1][1]);
        bool flag=check();
        if(!flag && dp[1][0] != dp[1][1]) cout << maxx << " Yes\n";
        else cout<< maxx << " No\n";
    }
    return 0;
}