1. 程式人生 > >題解報告:hdu 2094 產生冠軍

題解報告:hdu 2094 產生冠軍

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 產生冠軍