九度OJ-1450:产生冠军

题目描述:
有一群人,打乒乓球比赛,两两捉对撕杀,每两个人之间最多打一场比赛。
球赛的规则如下:
如果A打败了B,B又打败了C,而A与C之间没有进行过比赛,那么就认定,A一定能打败C。
如果A打败了B,B又打败了C,而且,C又打败了A,那么A、B、C三者都不可能成为冠军。
根据这个规则,无需循环较量,或许就能确定冠军。你的任务就是面对一群比赛选手,在经过了若干场撕杀之后,确定是否已经实际上产生了冠军。

输入:
输入含有一些选手群,每群选手都以一个整数n(n<1000)开头,后跟n对选手的比赛结果,比赛结果以一对选手名字(中间隔一空格)表示,前者战胜后者。如果n为0,则表示输入结束。

输出:
对于每个选手群,若你判断出产生了冠军,则在一行中输出“Yes”,否则在一行中输出“No”。

样例输入:
3
Alice Bob
Smith John
Alice Smith
5
a c
c d
d e
b e
a d
0
样例输出:
Yes
No
参考代码:

/*本题好像是判断拓扑排序的存在性,但是第二个例子说明产生冠军的情况是全图存在唯一入度为0的结点*/

#include<cstdio>
#include<iostream>
#include<cstring>
#include<map>
#include<string>
#include<vector>
using namespace std;
#define N 2010
map<string, int>ma;
//vector<int> edge[N];
int in[N];
char c1[101], c2[101];
string s1, s2;

int main() {
	int n;
	while (scanf("%d", &n) != EOF) {
		if (n == 0) break;
		for (int i = 1; i <= 2 * n; i++) {
			in[i] = 0;//注意这里输入n对关系,即最多可能存在2*n个队伍
		}
		ma.clear();
		int idx = 1;
		for (int i = 1; i <= n; i++) {
			scanf("%s%s", c1, c2);
			s1 = c1;
			s2 = c2;
			int idxa, idxb;
			if (ma.find(s1) == ma.end()) {
				idxa = idx;
				ma[s1] = idx++;;
			}
			else {
				idxa = ma[s1];
			}
			if (ma.find(s2) == ma.end()) {
				idxb = idx;
				ma[s2] = idx++;
			}
			else {
				idxb = ma[s2];
			}
			in[idxb]++;
		}
		int cnt = 0;
		for (int j = 1; j <idx; j++) {//注意这里不带等号,即使下标从1开始
			if (in[j] == 0)
				cnt++;
		}
		puts(cnt == 1 ? "Yes" : "No");
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/sinat_38292108/article/details/88343587
今日推荐