題解報告:hdu 2094 產生冠軍
阿新 • • 發佈:2018-04-07
pro script repeat-y clu back 目的 otto turn als
題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=2094
Problem Description 有一群人,打乒乓球比賽,兩兩捉對撕殺,每兩個人之間最多打一場比賽。 球賽的規則如下: 如果A打敗了B,B又打敗了C,而A與C之間沒有進行過比賽,那麽就認定,A一定能打敗C。 如果A打敗了B,B又打敗了C,而且,C又打敗了A,那麽A、B、C三者都不可能成為冠軍。 根據這個規則,無需循環較量,或許就能確定冠軍。你的任務就是面對一群比賽選手,在經過了若幹場撕殺之後,確定是否已經實際上產生了冠軍。 Input 輸入含有一些選手群,每群選手都以一個整數n(n<1000)開頭,後跟n對選手的比賽結果,比賽結果以一對選手名字(中間隔一空格)表示,前者戰勝後者。如果n為0,則表示輸入結束。 Output 對於每個選手群,若你判斷出產生了冠軍,則在一行中輸出“Yes”,否則在一行中輸出“No”。 Sample Input 3 Alice Bob Smith John Alice Smith 5 a c c d d e b e a d 0 Sample Output Yes No 解題思路:這道題要知道的是冠軍只有一個,題目的意思可能會使人想到另外的一些解法,比如並查集等等,但其實並不用這麽復雜,用C++裏面的set容器,其特點是容器元素具有唯一性,即去重。一個用來保存所有選手的名字,一個用來保存所有失敗的選手,set1容器大小-set2容器大小==1時,即產生唯一的冠軍,否則沒有冠軍。這裏提供兩種解法,一種是STL裏的set容器,另一種是C語言解法。 AC代碼: 解法一:C語言解法。二維數組模擬set容器。mark數組用來標記勝利與失敗情況。1#include <bits/stdc++.h> 2 using namespace std; 3 int main() 4 { 5 int n,i,mark[1005],sum; //n對選手,mark數組來標記勝利和失敗 6 char a[1005][20],b[20],c[20];//二維數組a模擬STL中set容器集合,元素具有唯一性,b打敗c 7 bool fb,fc;//標記當前輸入的b和c字符串是否出現過 8 while(cin>>n && n){ 9 getchar();//吃掉回車符 10 sum=i=0; 11 memset(mark,-1,sizeof(mark)); //全部初始化為-1,-1表示為冠軍 12 memset(a,0,sizeof(a));//a數組全部初始化為0 13 while (n--){ //n對選手 14 fb=fc=false; //標記為假 15 cin>>b>>c; 16 if(i==0){//處理第一對選手 17 strcpy(a[i++],b);//先把b,c分別賦值給a數組 18 strcpy(a[i++],c);19 mark[i-1]=0; //c對應下標標記存c字符串的結果為0,表示輸 20 } 21 else{//處理除第一對選手之外的選手情況 22 for(int j=0;j<i;j++){//循環到i-1即可,判斷以前是否出現過 23 if(strcmp(a[j],b)==0)fb = true;//標記b出現過 24 if(strcmp(a[j],c)==0){//比較c 25 mark[j]=0; //有的話順便將其置為0,因為是輸 26 fc=true; //同時標記出現過 27 } 28 } 29 if(!fb)strcpy(a[i++],b);//沒出現的話,還得賦值給a數組 30 if(!fc){ 31 strcpy(a[i++],c);//賦值給a數組之後還得讓對應的標記為0 32 mark[i-1]=0; 33 } 34 } 35 } 36 for(int j=0;j<i;j++) 37 if (mark[j]==-1)sum++;//統計mark數組勝利的人數 38 if (sum!=1)cout<<"No"<<endl;//沒有冠軍 39 else cout<<"Yes"<<endl; //產生冠軍 40 } 41 return 0; 42 }
解法二:使用STL中的set容器。
1 #include <bits/stdc++.h> 2 using namespace std; 3 int main() 4 { 5 int n; 6 string a,b; 7 set<string> all;//保存所有選手的名字 8 set<string> lose;//保存被打敗的選手名字 9 while(cin>>n && n){ 10 all.clear();//每次輸入選手群時清空兩個容器 11 lose.clear(); 12 while(n--){ 13 cin>>a>>b; 14 all.insert(a);//將兩個選手名字都插入到all容器中 15 all.insert(b); 16 lose.insert(b);//失敗的選手名字則插入到lose容器中 17 } 18 if(all.size()-lose.size()==1)//當所有選手人數和與被打敗選手人數和的差為1時,將產生冠軍 19 cout<<"Yes"<<endl; 20 else//否則沒有冠軍 21 cout<<"No"<<endl; 22 } 23 return 0; 24 }
題解報告:hdu 2094 產生冠軍