产生冠军 - 九度教程第 105 题

该博客介绍了九度教程第105题——通过乒乓球比赛结果预测冠军。题目要求在有限比赛中确定是否存在冠军。利用图论中的拓扑排序,通过选手间的胜负关系判断是否有唯一入度为零的节点,即冠军。博客还提到map数据结构在映射选手姓名到编号中的应用,以及其内部实现的红黑树。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

产生冠军 - 九度教程第 105 题

题目

时间限制:1 秒 内存限制:32 兆 特殊判题:否
题目描述:
有一群人,打乒乓球比赛,两两捉对撕杀,每两个人之间最多打一场比赛。球赛的规则如下:如果 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

这便是在图论中所讨论过的拓扑排序问题。将选手对应结点,胜负关系对应为结点之间的有
向边,可以产生冠军的情况即为全图中入度为零的点唯一。与普通的拓扑排序问题不同,这里需要将输入的选手姓名映射为结点编号,这就需要标准对象map。

#include <stdio.h>
#include <vector>
#include <map>//要使用map必须包含此头文件
#include <string>
#include <queue>

using namespace std;

map<string,int> M;//定义一个完成从string到int映射的map
int in[2002];

int main()
{
    int n;
    while(scanf("%d",&n)!=EOF && n!=0){
        for(int i=0;i<2*n;i++){//n组胜负关系,至多存在n个队伍
            in[i]=0;//初始化入度
        }

        M.clear();//对map中的映射关系清空

        int idx=0;//下一个被映射的数字
        for(int i=0;i<n;i++){
            char str1[50],str2[50];
            scanf("%s%s",str1,str2);//输入两个选手名称
            string a=str1,b=str2;//将字符串保存至string中
            int idxa,idxb;

            if(M.find(a)==M.end()){//若map中尚无对该a的映射
                idxa=idx;
                M[a]=idx++;//设定其映射为idx,并递增idx
            }else{
                idxa=M[a];//否则直接读出该映射
            }

            if(M.find(b)==M.end()){
                idxb=idx;
                M[b]=idx++;
                //map映射值从1开始计数,
                //相比入度数组in索引加1
            }else{
                idxb=M[b];//确定b的映射,方法与a相同
            }

            in[idxb]++;//b的入度递增
        }

        int cnt=0;
        for(int i=0;i<idx;i++){
            //确定所有映射数字的入度,
            //统计入度为0的个数
            if(in[i]==0)cnt++;
        }
        puts(cnt==1 ? "Yes" : "No");//若入度为0输出Yes,否则输出No
    }
    return 0;
}

如题所示,map很好的完成了从string到int的映射,即完成了选手姓名到结点编号的映射。下面回顾它的用法:

map<string,int> M;//定义一个完成从string到int映射的map
M.clear(); //清空一个map
M.find(b);//确定map中是否保存string对象b的映射,若没有函数返回M.end()
M[b] = idx; //若map中不存在string对象b的映射,则定义b映射为idx
idxb = M[b]; //若map中存在string对象b的映射,则读出该映射

在了解了以上map的用法和用处后,就能使用map完成特定类型变量之间的映射,而不需作过多的干预。顺便一提的是,map的内部实现是一棵红黑树。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值