hdu 2094 产生冠军(STL map || 拓扑 || STL set)

2024-03-27 23:32

本文主要是介绍hdu 2094 产生冠军(STL map || 拓扑 || STL set),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=23626

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
原来我是这样想的:只要只有一个入度是0的点那么就有唯一的冠军。于是愉快的敲完代码,测试完用例没有发现错误交上去结果不断的WA。。后来我发现问题出现在我使用的map上:
WA:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <map>
#include <string>
#include <cstring>
using namespace std;
const int maxn=2010;
int indegree[maxn],head[maxn],ip;
int n;
struct node{int v,next;
}edge[maxn];
void init(){ip=0;memset(indegree,0,sizeof(indegree));
}
void addedge(int u,int v){edge[ip].v=v;edge[ip].next=head[u];head[u]=ip++;indegree[v]++;//cout<<v<<" "<<indegree[v]<<endl;
}
map<string, int> mp;
int main()
{//freopen("cin.txt","r",stdin);while(cin>>n&&n){init();int top=0;for(int i=1;i<=n;i++){string s1,s2;cin>>s1>>s2;if(!mp[s1]){mp[s1]=++top;}if(!mp[s2]){mp[s2]=++top;}//cout<<mp[s1]<<" "<<mp[s2]<<endl;addedge(mp[s1],mp[s2]);}//for(int i=1;i<top;i++)cout<<i<<" "<<indegree[i]<<endl;sort(indegree+1,indegree+1+top);if(indegree[1]==0 && indegree[2]!=0 ) printf("Yes\n");else puts("No");}return 0;
}

比如这份测试用例:
5
a c
c d
d e
b e
a d
4
aa bb
bb cc
cc aa
dd aa

a b
b c
c a
d a 
第二个例子和第三个例子应该是一样的结果,但运行出来不对。因为第一个例子对第三个例子造成了“数据污染”。前面已经输入过a,b,c,d后面接着输入,mp[s1],mp[s2]的默认值不是0!单个例子我利用了map的“记忆”,可是多个例子它的记忆又导致了错误的产生。真是一把双刃剑。而用map<char*,int>更是不对。转念一想,把map放在主函数里不就能只在单个例子利用他的记忆吗!
AC:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <map>
#include <string>
#include <cstring>
using namespace std;
const int maxn=2010;
int indegree[maxn],head[maxn],ip;
int n;
struct node{int v,next;
}edge[maxn];
void init(){ip=0;memset(indegree,0,sizeof(indegree));
}
void addedge(int u,int v){edge[ip].v=v;edge[ip].next=head[u];head[u]=ip++;indegree[v]++;
}
int main()
{//freopen("cin.txt","r",stdin);while(cin>>n&&n){init();int top=0;   map<string, int> mp;for(int i=1;i<=n;i++){string s1,s2;cin>>s1>>s2;if(!mp[s1]){mp[s1]=++top;}if(!mp[s2]){mp[s2]=++top;}addedge(mp[s1],mp[s2]);}sort(indegree+1,indegree+1+top);if(indegree[1]==0 && indegree[2]!=0 ) printf("Yes\n");else puts("No");}return 0;
}
代码还能优化的。
不依赖于STL了。自己写函数联系字符串和数字:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int maxn=2010;
int indegree[maxn],ip;
int n;
char name[maxn][20];
int name_count;
void init(){ip=0;name_count=0;memset(indegree,0,sizeof(indegree));memset(name,0,sizeof(name));
}
int namedex(char s[]){int i;for(i=1;i<=name_count;i++){if(strcmp(s,name[i])==0) {return i;}}if(i>name_count) strcpy(name[++name_count],s);return name_count;
}
int main()
{//freopen("cin.txt","r",stdin);while(cin>>n&&n){init();for(int i=1;i<=n;i++){char s[20];cin>>s;int a=namedex(s);cin>>s;int b=namedex(s);indegree[b]++;}sort(indegree+1,indegree+1+name_count);if(indegree[1]==0 && indegree[2]!=0 ) printf("Yes\n");else puts("No");}return 0;
}
开始做这题很不顺的,有几个点:最开始认为图里存在子环是不可以的,后来才知道只要环不是连起所有元素的大环就可以。

比如上面的右边图,d能打败a,那么也间接的打败了b,c。所以d是冠军。
我也看了看其他大神的思路,有这样的解法(很妙~):输的人数比所有人数少1则有一个人没有输,他就是唯一的冠军。这得用好set。
#include <iostream>
#include <cstdio>
#include <set>
#include <string>
using namespace std;
const int maxn=2010;   
int n;
int main()
{//freopen("cin.txt","r",stdin);while(cin>>n&&n){int top=1;set<string> mp,key;for(int i=1;i<=n;i++){string s1,s2;cin>>s1>>s2;mp.insert(s1);mp.insert(s2);key.insert(s2);}if(mp.size()-key.size()==1) printf("Yes\n");else puts("No");}return 0;
}





这篇关于hdu 2094 产生冠军(STL map || 拓扑 || STL set)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/853761

相关文章

Java Map排序如何按照值按照键排序

《JavaMap排序如何按照值按照键排序》该文章主要介绍Java中三种Map(HashMap、LinkedHashMap、TreeMap)的默认排序行为及实现按键排序和按值排序的方法,每种方法结合实... 目录一、先理清 3 种 Map 的默认排序行为二、按「键」排序的实现方式1. 方式 1:用 TreeM

C++中unordered_set哈希集合的实现

《C++中unordered_set哈希集合的实现》std::unordered_set是C++标准库中的无序关联容器,基于哈希表实现,具有元素唯一性和无序性特点,本文就来详细的介绍一下unorder... 目录一、概述二、头文件与命名空间三、常用方法与示例1. 构造与析构2. 迭代器与遍历3. 容量相关4

Redis中Set结构使用过程与原理说明

《Redis中Set结构使用过程与原理说明》本文解析了RedisSet数据结构,涵盖其基本操作(如添加、查找)、集合运算(交并差)、底层实现(intset与hashtable自动切换机制)、典型应用场... 目录开篇:从购物车到Redis Set一、Redis Set的基本操作1.1 编程常用命令1.2 集

深入解析C++ 中std::map内存管理

《深入解析C++中std::map内存管理》文章详解C++std::map内存管理,指出clear()仅删除元素可能不释放底层内存,建议用swap()与空map交换以彻底释放,针对指针类型需手动de... 目录1️、基本清空std::map2️、使用 swap 彻底释放内存3️、map 中存储指针类型的对象

C++ STL-string类底层实现过程

《C++STL-string类底层实现过程》本文实现了一个简易的string类,涵盖动态数组存储、深拷贝机制、迭代器支持、容量调整、字符串修改、运算符重载等功能,模拟标准string核心特性,重点强... 目录实现框架一、默认成员函数1.默认构造函数2.构造函数3.拷贝构造函数(重点)4.赋值运算符重载函数

java -jar example.jar 产生的日志输出到指定文件的方法

《java-jarexample.jar产生的日志输出到指定文件的方法》这篇文章给大家介绍java-jarexample.jar产生的日志输出到指定文件的方法,本文给大家介绍的非常详细,对大家的... 目录怎么让 Java -jar example.jar 产生的日志输出到指定文件一、方法1:使用重定向1、

Kotlin Map映射转换问题小结

《KotlinMap映射转换问题小结》文章介绍了Kotlin集合转换的多种方法,包括map(一对一转换)、mapIndexed(带索引)、mapNotNull(过滤null)、mapKeys/map... 目录Kotlin 集合转换:map、mapIndexed、mapNotNull、mapKeys、map

c++中的set容器介绍及操作大全

《c++中的set容器介绍及操作大全》:本文主要介绍c++中的set容器介绍及操作大全,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录​​一、核心特性​​️ ​​二、基本操作​​​​1. 初始化与赋值​​​​2. 增删查操作​​​​3. 遍历方

shell中set -u、set -x、set -e的使用

《shell中set-u、set-x、set-e的使用》本文主要介绍了shell中set-u、set-x、set-e的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参... 目录✅ 1. set -u:防止使用未定义变量 作用: 示例:❌ 报错示例输出:✅ 推荐使用场景:✅ 2. se

Java中Map.Entry()含义及方法使用代码

《Java中Map.Entry()含义及方法使用代码》:本文主要介绍Java中Map.Entry()含义及方法使用的相关资料,Map.Entry是Java中Map的静态内部接口,用于表示键值对,其... 目录前言 Map.Entry作用核心方法常见使用场景1. 遍历 Map 的所有键值对2. 直接修改 Ma