【POJ - 3342】Party at Hali-Bula(树形dp,最大独立集,是否有唯一解)
題干:
Dear Contestant,
I'm going to have a party at my villa at Hali-Bula to celebrate my retirement from BCM. I wish I could invite all my co-workers, but imagine how an employee can enjoy a party when he finds his boss among the guests! So, I decide not to invite both an employee and his/her boss. The organizational hierarchy at BCM is such that nobody has more than one boss, and there is one and only one employee with no boss at all (the Big Boss)! Can I ask you to please write a program to determine the maximum number of guests so that no employee is invited when his/her boss is invited too? I've attached the list of employees and the organizational hierarchy of BCM.
Best,
--Brian Bennett
P.S. I would be very grateful if your program can indicate whether the list of people is uniquely determined if I choose to invite the maximum number of guests with that condition.
Input
The input consists of multiple test cases. Each test case is started with a line containing an integer?n?(1 ≤?n?≤ 200), the number of BCM employees. The next line contains the name of the Big Boss only. Each of the following?n-1 lines contains the name of an employee together with the name of his/her boss. All names are strings of at least one and at most 100 letters and are separated by blanks. The last line of each test case contains a single 0.
Output
For each test case, write a single line containing a number indicating the maximum number of guests that can be invited according to the required condition, and a word Yes or No, depending on whether the list of guests is unique in that case.
Sample Input
6 Jason Jack Jason Joe Jack Jill Jason John Jack Jim Jill 2 Ming Cho Ming 0Sample Output
4 Yes 1 No題目大意:
在一個公司中要舉辦一個聚會,每一個員工有一個奉獻值。為了和諧規定直接上下級不能一起出席。
解題報告:
? ?這道題麻煩的地方在于需要判斷是否方案數唯一。。。首先你要知道我們的答案中一定每個頂點都用到了dp[][0]或者dp[][1]這兩個狀態中的一個,所以你就想,,(假設父節點u子節點v)如果我當前節點用的是dp[u][1],那么對于子節點就制造不出矛盾,如果我用的是dp[u][0],那么我們就可以看子節點是否有矛盾(因為這時候子節點是可以選擇的),如果我選和不選都可以取到max,那么矛盾就出來了。(有的同學會問,你這一個點取到max有啥用,萬一我不取這一分支呢,但是其實是不存在這種顧慮的,因為你是dp啊,有更大的值肯定會選啊,,其實究其原因還是那句“最終的答案中一定每個頂點都用到了dp[][0]或者dp[][1]這兩個狀態中的一個”,,所以這倆狀態哪個更大我肯定會取這個值,,(好吧其實還是用一個標記數組直接遞推上去比較靠譜))
AC代碼:
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define ll long long #define pb push_back #define pm make_pair #define fi first #define se second using namespace std; const int MAX = 2e5 + 5; map<string,int> mp; vector<int >vv[505]; char s[205],s1[205],s2[205]; int dp[505][2]; int haha; void dfs(int cur,int root) {dp[cur][1]=1;int up = vv[cur].size();for(int i = 0; i<up; i++) {int v = vv[cur][i];if(v == root) continue;dfs(v,cur);dp[cur][1] += dp[v][0];dp[cur][0] += max(dp[v][0],dp[v][1]);}for(int i = 0; i<up; i++) {int v = vv[cur][i];if(v == root) continue;if(dp[cur][0] > dp[cur][1] && dp[v][0] == dp[v][1]) haha=0;} } int main() {int n,tot;while(~scanf("%d",&n)) {if(n == 0) break; haha=1;mp.clear();for(int i = 1; i<=n; i++) vv[i].clear();memset(dp,0,sizeof dp);tot=0;scanf("%s",s);mp[s] = ++tot;for(int i = 1; i<=n-1; i++) {scanf("%s%s",s1,s2);if(mp.find(s1) == mp.end()) mp[s1] = ++tot;if(mp.find(s2) == mp.end()) mp[s2] = ++tot;int t1=mp[s1],t2=mp[s2];vv[t1].pb(t2);vv[t2].pb(t1);}dfs(1,0);printf("%d ",max(dp[1][0],dp[1][1]));if(dp[1][0] == dp[1][1]) haha=0;if(haha == 1) printf("Yes");else printf("No");printf("\n");}return 0 ;}?
錯誤代碼1:
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define ll long long #define pb push_back #define pm make_pair #define fi first #define se second using namespace std; const int MAX = 2e5 + 5; map<string,int> mp; vector<int >vv[505]; char s[205],s1[205],s2[205]; int dp[505][2]; int qq[505]; int forbid; void dfs(int cur,int root) {if(cur != forbid)dp[cur][1]=1;int up = vv[cur].size();for(int i = 0; i<up; i++) {int v = vv[cur][i];if(v == root) continue;dfs(v,cur);if(cur != forbid) dp[cur][1] += dp[v][0];dp[cur][0] += max(dp[v][0],dp[v][1]);} } int main() {int n,tot;while(~scanf("%d",&n)) {if(n == 0) break; forbid=-1;mp.clear();for(int i = 1; i<=n; i++) vv[i].clear();memset(dp,0,sizeof dp);memset(qq,0,sizeof qq);tot=0;scanf("%s",s);mp[s] = ++tot;for(int i = 1; i<=n-1; i++) {scanf("%s%s",s1,s2);if(mp.find(s1) == mp.end()) mp[s1] = ++tot;if(mp.find(s2) == mp.end()) mp[s2] = ++tot;int t1=mp[s1],t2=mp[s2];vv[t1].pb(t2);vv[t2].pb(t1);}dfs(1,0);printf("%d ",max(dp[1][0],dp[1][1]));int ans = max(dp[1][0],dp[1][1]);int cnt = 0;for(int i = 1; i<=n; i++) {forbid = i;if(max(dp[1][0],dp[1][1]) == ans) cnt++;}if(cnt == 1) printf("Yes");else printf("No");printf("\n");}return 0 ;}錯誤代碼2:
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define ll long long #define pb push_back #define pm make_pair #define fi first #define se second using namespace std; const int MAX = 2e5 + 5; map<string,int> mp; vector<int >vv[505]; char s[205],s1[205],s2[205]; int dp[505][2]; int qq[505]; int haha; void dfs(int cur,int root) {dp[cur][1]=1;int up = vv[cur].size();for(int i = 0; i<up; i++) {int v = vv[cur][i];if(v == root) continue;dfs(v,cur);dp[cur][1] += dp[v][0];dp[cur][0] += max(dp[v][0],dp[v][1]);} } void DFS(int cur,int root,int res) {if(res == 1) haha++;int up = vv[cur].size();for(int i = 0; i<up; i++) {int v = vv[cur][i];if(v == root) continue;if(max(dp[v][0],dp[v][1]) == res-1)DFS(v,cur,res-1);} } int main() {int n,tot;while(~scanf("%d",&n)) {if(n == 0) break; haha=0;mp.clear();for(int i = 1; i<=n; i++) vv[i].clear();memset(dp,0,sizeof dp);memset(qq,0,sizeof qq);tot=0;scanf("%s",s);mp[s] = ++tot;for(int i = 1; i<=n-1; i++) {scanf("%s%s",s1,s2);if(mp.find(s1) == mp.end()) mp[s1] = ++tot;if(mp.find(s2) == mp.end()) mp[s2] = ++tot;int t1=mp[s1],t2=mp[s2];vv[t1].pb(t2);vv[t2].pb(t1);}dfs(1,0);printf("%d ",max(dp[1][0],dp[1][1]));int ans = max(dp[1][0],dp[1][1]);DFS(1,0,ans); // int cnt = 0; // for(int i = 1; i<=n; i++) { // if(max(dp[1][0],dp[1][1]) == ans) cnt++; // } // //printf("%d",mp["Jill"]);if(haha == 1) printf("No");else printf("Yes");printf("\n");}return 0 ;}錯誤代碼3:
#include<cstdio> #include<iostream> #include<algorithm> #include<queue> #include<map> #include<vector> #include<set> #include<string> #include<cmath> #include<cstring> #define ll long long #define pb push_back #define pm make_pair #define fi first #define se second using namespace std; const int MAX = 2e5 + 5; map<string,int> mp; vector<int >vv[505]; char s[205],s1[205],s2[205]; int dp[505][2]; int qq[505]; int haha; void dfs(int cur,int root) {dp[cur][1]=1;int up = vv[cur].size();for(int i = 0; i<up; i++) {int v = vv[cur][i];if(v == root) continue;dfs(v,cur);dp[cur][1] += dp[v][0];dp[cur][0] += max(dp[v][0],dp[v][1]);} } void DFS(int cur,int root,int res,bool cho) {//cho==0代表當前點沒選 //ok==0代表當前點不能選 if(res == 1) {haha++;return ;}int up = vv[cur].size();for(int i = 0; i<up; i++) {int v = vv[cur][i];if(v == root) continue;//if(max(dp[v][0],dp[v][1]) == res-1)if(cho == 1) {if(dp[v][0] == res-1) DFS(v,cur,res-1,0);}else {if(dp[v][0] == res-1) DFS(v,cur,res-1,0);if(dp[v][1] == res-1) DFS(v,cur,res-1,1);}} } int main() {int n,tot;while(~scanf("%d",&n)) {if(n == 0) break; haha=0;mp.clear();for(int i = 1; i<=n; i++) vv[i].clear();memset(dp,0,sizeof dp);memset(qq,0,sizeof qq);tot=0;scanf("%s",s);mp[s] = ++tot;for(int i = 1; i<=n-1; i++) {scanf("%s%s",s1,s2);if(mp.find(s1) == mp.end()) mp[s1] = ++tot;if(mp.find(s2) == mp.end()) mp[s2] = ++tot;int t1=mp[s1],t2=mp[s2];vv[t1].pb(t2);vv[t2].pb(t1);}dfs(1,0);printf("%d ",max(dp[1][0],dp[1][1]));int ans = max(dp[1][0],dp[1][1]);if(dp[1][1] == ans) {DFS(1,0,ans,1);}if(dp[1][0] == ans) {DFS(1,0,ans,0);} // DFS(1,0,ans); // int cnt = 0; // for(int i = 1; i<=n; i++) { // if(max(dp[1][0],dp[1][1]) == ans) cnt++; // } // //printf("%d",mp["Jill"]);if(haha == 1) printf("Yes");else printf("No");printf("\n");}return 0 ;}用二維數組標記的dfs(Orzwjh大佬)
void dfs(int rt) {for(int i=head[rt];i!=-1;i=side[i].nex){int ty=side[i].v;dfs(ty);if(mk[ty][0]==1){mk[rt][1]=1;}dp[rt][1]+=dp[ty][0];if(dp[ty][0]==dp[ty][1]){dp[rt][0]+=dp[ty][0];mk[rt][0]=1;}else if(dp[ty][0]>dp[ty][1]){dp[rt][0]+=dp[ty][0];if(mk[ty][0]==1)mk[rt][0]=1;}else{dp[rt][0]+=dp[ty][1];if(mk[ty][1]==1)mk[rt][0]=1;}} }總結 記住了一直都是用孩子節點的值去更新父親節點的值就好了。
總結
以上是生活随笔為你收集整理的【POJ - 3342】Party at Hali-Bula(树形dp,最大独立集,是否有唯一解)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微信上线“大爆炸”功能:长按图片即可提取
- 下一篇: 【HDU - 薛猫猫杯程序设计网络赛】【