下面的是从该网站上copy过来的,稍微改了一点,给出链接:http://hi.baidu.com/nondes/item/26dd0f1a02b1e0ef5f53b1c7

题意:有N个人玩剪刀石头布,其中有个人是裁判,其他人分为3组。 这3组中每个组分别出剪刀,石头和布。 裁判可以任意出3个中的一个。 现在有M个回合,每个回合从N个人中任意选出两个人来玩,并给出结果。 要求输出最早找出裁判的回合数,以及裁判的编号! 还有可能无法确定,或者不可能出现这种结果。

思路:利用并查集可以建立起相对关系,但是问题出在裁判可以任意出招,也就是说通过裁判建立起来的任何关系都是不可靠的。 所以不能通过裁判来建立任何关系。

  于是可以枚举裁判是哪一个,对有他参与的回合不予处理! 接下来就是如何确定他是不是裁判!

  假设当前某个人作为裁判,在他不参与的回合中出现了矛盾,那么这个人一定就不是裁判。

  1.如果存在着一个真实的裁判,那么枚举他的时候不会出现矛盾,而枚举其他人的时候一定会出现矛盾。

  2.如果有大于1个不出现任何矛盾的情况,则就是不能确定的!

  3.而对于所有枚举都出现矛盾的时候,即所有小孩都不是裁判,则这是不可能的。因为如果出现矛盾,那么其中至少有一个“临时”裁判,枚举到他的时候就应该不出现矛盾!

  怎么确定最早发现裁判的回合数:

  对每一轮枚举,发现矛盾最早时刻是error[i],那么确定裁判的回合数一定是max(error[i])。

  对于处理并查集的时候,可以通过记录一个val[i]表示他与父亲节点的关系:

   val[i]==0:表示他和父亲同组; val[i]==1:表示父亲所在的组能赢过他; val[i]==2:表示他能赢过父亲所在的组;

再附上从一个网站上看到的,自己修改了一点,后来找不到网址了,给出不了链接了。。。原作者原谅啊。。。

  其实这题跟食物链完全一个磨子,同样三类食物,同样的互相制约关系。但这题有个judge,他可以出任意手势。

  于是我们的做法是,枚举每个小孩为裁判,判断他为裁判时在第几句话出错error[i](即到第几句话能判断该小孩不是裁判)。

  1. 如果只有1个小孩是裁判时,全部语句都是正确的,说明该小孩是裁判,那么判断的句子数即为其他小孩的error[i]的最大值。

  2. 如果每个小孩为裁判时,都可以找到矛盾的语句,则他们都不是裁判,那么就是impossible。

  3. 多于1个小孩为裁判时,没有找到矛盾的语句,就是Can not determine。

至于为什么判断的句子数是其他小孩的error[i]的最大值max,因为至少需要max行语句,才能使得其他小孩“做裁判”时找出矛盾的语句。

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm> /*
AC 579ms
枚举+带权并查集,如何判断最后输出结果的时候比较难
*/
using namespace std;
const int maxn=;
int n,m,num;//num为枚举完所有人后,其中不矛盾的个数(即有多少个人"做裁判"时,剩下的数据中没有出现矛盾)
int father[maxn];
int val[maxn]; //相对父节点的关系,平局:0,输:1(输给父节点),赢:2(赢了父节点)
int error[maxn];//error[i]表示枚举i做裁判时,矛盾出现在第几行
char str[][]; struct Node{
int a,b,c; //a<b,a>b,a=b,c存储的是b相对a的关系:平局:0,输:1,赢:2
}node[]; void init(){
for(int i=;i<maxn;i++){
father[i]=i;
val[i]=;
}
} int find_root(int x){
if(father[x]==x)
return x;
int tmp=father[x];
father[x]=find_root(father[x]);
val[x]=(val[x]+val[tmp])%;
return father[x];
} void Union(int x,int y,int fx,int fy,int c){
father[fy]=fx;
val[fy]=(-val[y]+c+val[x])%;
}
//求每次询问时的a,b,c的值,存入node数组中
void abc(int j){
node[j].a=node[j].b=node[j].c=;
int len=strlen(str[j]),i;
for(i=;i<len;i++){
if(str[j][i]=='<'){
node[j].c=;
break;
}
else if(str[j][i]=='>'){
node[j].c=;
break;
}
//额,原本就直接写了个else。。。
else if(str[j][i]=='='){
node[j].c=;
break;
}
}
for(int k=;k<i;k++){
node[j].a*=;
node[j].a+=str[j][k]-;
}
for(int k=i+;k<len;k++){
node[j].b*=;
node[j].b+=str[j][k]-;
}
}
int main()
{
int a,b,c;
int ans,round; //ans存储裁判的编号,round存储在第几行可判断出裁判
while(scanf("%d%d",&n,&m)!=EOF){
init();
memset(error,,sizeof(error));
num=;
round=;
for(int i=;i<=m;i++){
scanf("%s",str[i]);
abc(i);
}
/*
我知道原本错哪里了啊,小孩的编号不仅仅只有一位数。。。如12<13,100<101。。。
*/
for(int i=;i<n;i++){
init(); //每次枚举之前都要初始化。。。
for(int j=;j<=m;j++){
a=node[j].a;
b=node[j].b;
c=node[j].c;
if(a==i || b==i)
continue;
int fa=find_root(a);
int fb=find_root(b);
if(fa==fb){
int t=(val[b]+-val[a])%;
if(t!=c){
error[i]=j;
break;
}
}
else{
Union(a,b,fa,fb,c);
}
}
}
for(int i=;i<n;i++){
round=max(round,error[i]);
if(error[i]==){
ans=i;
num++;
}
}
//只有一个小孩,当他作为裁判时,全部语句都正确,则他为裁判
if(num==){
printf("Player %d can be determined to be the judge after %d lines\n",ans,round);
}
//当有多个小孩,当他作为裁判时,全部语句都正确,则无法确定
else if(num>){
printf("Can not determine\n");
}
//所有小孩作为裁判时,语句都有矛盾的地方,即他们都不是裁判,显然不可能
else{
printf("Impossible\n");
}
}
return ;
}

POJ 2912 Rochambeau(难,好题,枚举+带权并查集)的更多相关文章

  1. 【poj 1988】Cube Stacking(图论--带权并查集)

    题意:有N个方块,M个操作{"C x":查询方块x上的方块数:"M x y":移动方块x所在的整个方块堆到方块y所在的整个方块堆之上}.输出相应的答案. 解法: ...

  2. 【poj 1962】Corporative Network(图论--带权并查集 模版题)

    P.S.我不想看英文原题的,但是看网上题解的题意看得我 炒鸡辛苦&一脸懵 +_+,打这模版题的代码也纠结至极了......不得已只能自己翻译了QwQ . 题意:有一个公司有N个企业,分成几个网 ...

  3. (中等) POJ 1703 Find them, Catch them,带权并查集。

    Description The police office in Tadu City decides to say ends to the chaos, as launch actions to ro ...

  4. POJ 1984 Navigation Nightmare(二维带权并查集)

    题目链接:http://poj.org/problem?id=1984 题目大意:有n个点,在平面上位于坐标点上,给出m关系F1  F2  L  D ,表示点F1往D方向走L距离到点F2,然后给出一系 ...

  5. POJ 1703 Find them, Catch them(带权并查集)

    传送门 Find them, Catch them Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 42463   Accep ...

  6. poj 1703 - Find them, Catch them【带权并查集】

    <题目链接> 题目大意: 已知所有元素要么属于第一个集合,要么属于第二个集合,给出两种操作.第一种是D a b,表示a,b两个元素不在一个集合里面.第二种操作是A a b,表示询问a,b两 ...

  7. poj 2492 A Bug's Life【带权并查集】

    就是给一个无向图判是否有奇环 用带权并查集来做,边权1表示连接的两个节点异性,否则同性,在%2意义下进行加法运算即可,最后判相同的时候也要%2,因为可能有负数 #include<iostream ...

  8. POJ 2912 - Rochambeau - [暴力枚举+带权并查集]

    题目链接:http://poj.org/problem?id=2912 Time Limit: 5000MS Memory Limit: 65536K Description N children a ...

  9. poj 2912 Rochambeau(枚举+带权并查集)

    题目链接:http://poj.org/problem?id=2912 题意:多个人玩石头剪刀布分成3组和一个裁判,每一组提前选定了自己出哪个手势,裁判可以随意出什么手势,问是否能够从给出的一系列石头 ...

随机推荐

  1. SVN常见问题处理

    1.SVN 提交时报错:Path is not a working copy directory   (1)报这个错通常是因为这个文件夹或其上层文件夹不是checkout或update出来的. 使用S ...

  2. C++ 11 之推导关键词

    C++ 11新增了两个推导关键词,auto & decltype 1.区别 auto:用于推导变量类型: decltype: 用于推导表达式或者函数返回值 2.直接上代码 intmain() ...

  3. spring与MyBatis结合

    下面将介绍使用spring+mybatis的开发样例: 首先,笔者创建的是一个maven工程,在开发先先导入相关的依赖jar: pom.xml: <dependencies> <de ...

  4. C#中的interface、virtual和abstract

    一.Abstract: abstract方法必须在abstarct类中声明,没有默认实现,子类必须实现. 二.Virtual: virtual方法可以声明在abstract类中,也可以声明在非abst ...

  5. Log Parser 2.2

    Log Parser 2.2 是一个功能强大的通用工具,它可对基于文本的数据(如日志文件.XML 文件和 CSV 文件)以及 Windows 操作系统上的重要数据源(如事件日志.注册表.文件系统和 A ...

  6. linux c 打印彩色字符

    #include <stdio.h> #include <string.h> int main(int argc, char **argv) { , j = , str_len ...

  7. TAG的用法和用途[转]

    用一个例子来说明:一个combobox控件...一个textBox控件...一个datagridview控件!datagridview控件是连接数据库的...combobox和textBox是联合查询 ...

  8. Jquery post 传递数组给asp.net mvc方法

    以批量删除数据为例  做批量删除会需要传递要删除的数据ID数组 function RemoveLog(){ var postModel=[]; //遍历复选框获取要删除的数据ID 存放到数组中  $( ...

  9. 微软职位内部推荐-Senior Dev Lead

    微软近期Open的职位: Bing Index Serve team is hiring! We are one of the core teams in Bing serving more than ...

  10. cocos2dx中的坐标体系

    1.UI坐标系和GL坐标系 2.本地坐标与世界坐标 本地坐标是一个相对坐标,是相对于父节点或者你指明的某个节点的相对位置来说的,本地坐标的原点在参考节点的左下角 世界坐标是一个绝对的坐标,是以屏幕的左 ...