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