链接: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;
}