日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【POJ - 3342】Party at Hali-Bula(树形dp,最大独立集,是否有唯一解)

發布時間:2023/12/10 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【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 0

Sample 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,最大独立集,是否有唯一解)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。