题解报告:hdu 2094 产生冠军

题目链接: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 }

原文地址:https://www.cnblogs.com/acgoto/p/8729175.html

时间: 2024-10-18 10:59:13

题解报告:hdu 2094 产生冠军的相关文章

HDU 2094 产生冠军 (字典树+拓扑)

产生冠军 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 8591    Accepted Submission(s): 4047 Problem Description 有一群人,打乒乓球比赛,两两捉对撕杀,每两个人之间最多打一场比赛. 球赛的规则如下: 如果A打败了B,B又打败了C,而A与C之间没有进行过比赛,那么就认定,A一定能打

HDU 2094 产生冠军 hash 水题

Problem Description 有一群人,打乒乓球比赛,两两捉对撕杀,每两个人之间最多打一场比赛.球赛的规则如下:如果A打败了B,B又打败了C,而A与C之间没有进行过比赛,那么就认定,A一定能打败C.如果A打败了B,B又打败了C,而且,C又打败了A,那么A.B.C三者都不可能成为冠军.根据这个规则,无需循环较量,或许就能确定冠军.你的任务就是面对一群比赛选手,在经过了若干场撕杀之后,确定是否已经实际上产生了冠军. Input 输入含有一些选手群,每群选手都以一个整数n(n<1000)开头

hdu 2094 产生冠军

题意:给出n对选手姓名,每对表示前者赢后者,求整场比赛是否有冠军: 思路:将名字用数字表示,离散化,然后就是裸裸的拓扑排序,只需判断初始时入度为0的是否唯一: #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n,m,i,j,k,con; int mm[1001][1001],indegree[500010]; char s1[500010],s2[500010

HDU 2094产生冠军(拓扑排序)

产生冠军 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 10374    Accepted Submission(s): 4857 Problem Description 有一群人,打乒乓球比赛,两两捉对撕杀,每两个人之间最多打一场比赛. 球赛的规则如下: 如果A打败了B,B又打败了C,而A与C之间没有进行过比赛,那么就认定,A一定能

题解报告:hdu 1162 Eddy&#39;s picture

Problem Description Eddy begins to like painting pictures recently ,he is sure of himself to become a painter.Every day Eddy draws pictures in his small room, and he usually puts out his newest pictures to let his friends appreciate. but the result i

线段树&#183;题解报告

线段树·题解报告 参考资料 ·课件 线段树 --刘汝佳 统计的力量,线段树全接触 --张昆玮 ·Blog [完全版]线段树 从普通线段树到zkw线段树 [总结][数据结构]ZKW线段树详解 选题目录 · Hdu1166 敌兵布阵(单点更新,区间求和) · Hdu1754 I Hate It(单点更新,RMQ) · Hdu3308 LCIS(单点更新,区间并) · Poj3468 A Simple Problem with Integers(区间加减,区间求和) · Poj2777 Count C

题解报告(CDUT暑期集训——第三场)

题解报告(CDUT暑期集训--第三场) A - Problem A. Ascending Rating HDU - 6319 思路:单调队列板子题?(但是弱的一批的我还是不会用(有空补上 用的滑动窗口算法 按着题解的从后往前做(ps:菜是原罪 AC代码 #include<stdio.h> #include<iostream> #include<math.h> #include<algorithm> #include<string.h> #incl

cojs 强连通图计数1-2 题解报告

OwO 题目含义都是一样的,只是数据范围扩大了 对于n<=7的问题,我们直接暴力搜索就可以了 对于n<=1000的问题,我们不难联想到<主旋律>这一道题 没错,只需要把方程改一改就可以了 首先我们考虑不合法的方案强连通分量缩点后一定是DAG 考虑子问题:DAG计数 做法可以参考<cojs DAG计数1-4 题解报告> 这里给出转移方程 f(n)=sigma((-1)^(k-1)*C(n,k)*2^(k*(n-k))*f(n-k)) 如果考虑上强连通分量缩点的情况呢? 我

2016 年宁波工程学院第七届ACM校赛题解报告

2016 年宁波工程学院第七届ACM校赛题解报告 本题解代码直接为比赛代码,仅供参考. A,B,C,D,G,H,J,K,L,M 来自 Ticsmtc 同学. F 来自 Gealo 同学. E,I 来自Alex 学长. Promblem A :    Two Sum 时间限制: 1 Sec  内存限制: 64 MB 题目描述: 给出n个数,另外给出?个整数S,判断是否可以从中取出2个数,使得这两个数的和是S. 输入: 第?行有个整数T(1 <= T <= 10),代表数据组数. 对于每组数据,第