杭电OJ-- 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
 
思路其实很简单:

如果A打败了B,那么B一定不能成为冠军,有了这一条,一切都好办了,首先将所有的对手标记为成功,对于输入的每一个结果,如

Alice Bob,将Bob标记为失败,依次处理,到了最后再查看标记,如果成功的标记只有一条,那么一定能够行,输出Yes,没有成功的标记或者标记大于1,比赛没有冠军,输出No。

代码如下:

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <string>
#include <map>
using namespace std;

#define MAX_NUM 2000
#define MAX_NAME_LEN 32


int main()
{
	//思路:只需要判断谁不是冠军即可
	int mark[MAX_NUM]; //标记数组
	int num_of_demo; //测试的组数
    
	while (scanf("%d", &num_of_demo) && num_of_demo != 0)
	{
		string first_name, second_name;
		memset(mark, 0, sizeof(mark));
		map<string, int> name_map;
		int index = 0; //指示器
		int count = 0;
		for (int i = 0; i < num_of_demo; ++i)
		{
			//scanf("%s %s", &first_name, &second_name);
			cin >> first_name >> second_name;
			map<string, int>::iterator it1, it2;
			it1 = name_map.find(first_name);
			it2 = name_map.find(second_name);

			if (it1 == name_map.end())
			{//如果不存在,插入
				name_map.insert(make_pair(first_name, index++));
			}
			if (it2 == name_map.end())
			{
				name_map.insert(make_pair(second_name, index++));
				mark[index - 1] = -1; //该位不可能成为冠军
			}
			else
			{
				mark[it2->second] = -1;
			}
		}

		for (int i = 0; i < index; ++i)
		{
			if (mark[i] == 0)
			{
				count++;
			}
		}
		if (count == 1)
		{
			cout << "Yes" << endl;
		}
		else
		{
			cout << "No" << endl;
		}
	}

	return 0;
}




你可能感兴趣的:(杭电OJ-- 2094 产生冠军)