题目链接:https://vjudge.net/problem/UVA-1220
思路:
- 树形DP模板题,求最大人数很简单,难点在于如何判断最大人数的名单是否有不同的情况;
- 解决方法是用一个数组f[manx][2]记录该节点是否出场的情况,为真时代表有多种情况;
- 具体讨论:
- 当父节点的值加上某个子节点的值时,他的f的情况也和该子节点一样;
- 当某个节点dp(i, 0) == dp(i, 1), 则该节点以及它的父节点也一定有多种情况(父节点必定取其中之一)。
Code:
1 #include<bits/stdc++.h> 2 using namespace std; 3 map<string, int> mp; 4 vector<int> T[210]; 5 int dp[210][2]; 6 bool f[210][2]; 7 8 void dfs(int x, int fa) { 9 int len = T[x].size(); 10 for (int i = 0; i < len; ++i) 11 dfs(T[x][i], x); 12 dp[fa][1] += dp[x][0]; 13 if (f[x][0]) f[fa][1] = 1; 14 if (dp[x][1] > dp[x][0]) { 15 dp[fa][0] += dp[x][1]; 16 if (f[x][1]) f[fa][0] = 1; 17 } 18 else { 19 dp[fa][0] += dp[x][0]; 20 if (f[x][0] || dp[x][1] == dp[x][0]) f[fa][0] = 1; 21 } 22 } 23 24 int main() { 25 int n, tot; 26 string boss, fa, son; 27 while(cin>>n, n) { 28 memset(dp, 0, sizeof(dp)); 29 memset(f, 0, sizeof(f)); 30 mp.clear(); 31 cin>>boss; 32 mp[boss] = tot = 1; 33 int ff, s; 34 for (int i = 1; i < n; ++i) { 35 cin>>son>>fa; 36 if (mp.count(fa)) ff = mp[fa]; 37 else ff = ++tot, mp[fa] = ff; 38 if (mp.count(son)) s = mp[son]; 39 else s = ++tot, mp[son] = s; 40 T[ff].push_back(s); 41 dp[i][1] = 1; 42 } 43 dp[n][1] = 1; 44 dfs(1, 0); 45 bool flag = 1; 46 int ans = max(dp[1][0], dp[1][1]); 47 if (dp[1][1] == dp[1][0]) flag = 0; 48 else if (dp[1][1] > dp[1][0]) {if (f[1][1]) flag = 0;} 49 else if (dp[1][1] < dp[1][0]) {if (f[1][0]) flag = 0;} 50 cout<<ans<<" "; 51 if (flag) cout<<"Yes"<<endl; 52 else cout<<"No"<<endl; 53 for (int i = 0; i <= n; ++i) T[i].clear(); 54 } 55 56 return 0; 57 }
时间: 2024-12-05 07:46:56