下面的是从该网站上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. OpenGL第6、7讲小结

    因为内容比较多,所以只看了两讲(强行解释). 一讲讲了如何给各个面贴纹理,一讲讲了加光照和按键控制. 现在讲的都是给规则的面贴纹理,像正方形,刚好纹理图也是正方形,那像人物模型的衣服贴起来用代码控制得 ...

  2. 使用zookeeper实现分布式master选举(c 接口版本)

    zookeeper,已经被很多人所熟知,主要应用场景有(数据订阅/发布 ,负载均衡, 命名服务, 分布式协调/通知,集群管理,Master选举,分布式锁,分布式队列). C接口的描述  主要参考 Ha ...

  3. silverlight将字符串转化为控件

    silverlight的System.Windows.Markup命名空间下,提供了XamlReader.Load()方法可以将字符串转换为控件. 代码 StringBuilder sbGrid = ...

  4. jeecms获取栏目标题图

    [@cms_channel id='1'] <img src="${tag_bean.titleImg!site.typeImg}" /> [/@cms_channel ...

  5. C++ socket编程

    源代码项目下载:http://download.csdn.net/detail/mmyzlinyingjie/7049499 TCP类的: TcpServer.cpp //WSAStartup soc ...

  6. Spark菜鸟学习营Day3 RDD编程进阶

    Spark菜鸟学习营Day3 RDD编程进阶 RDD代码简化 对于昨天练习的代码,我们可以从几个方面来简化: 使用fluent风格写法,可以减少对于中间变量的定义. 使用lambda表示式来替换对象写 ...

  7. C程序调用shell脚本共有三种方法

    C程序调用shell脚本共有三种法子 :system().popen().exec系列函数call_exec1.c ,内容为:system() 不用你自己去产生进程,它已经封装了,直接加入自己的命令e ...

  8. Ubuntu中NetBeans C/C++配置、编译

    系统环境:Ubuntu 9.04软件环境:NetBeans 6.7.1 C/C++ .JDK1.6.0_16本次目的:完成NetBeans 6.7.1 C/C++ 的配置工作.编译测试及对中文支持 首 ...

  9. How To Fix – Mcrypt PHP extension required in Laravel on Mac OS X (No MAMP)

    Laravel PHP web framework requires certain libraries to function properly. One of these libraries is ...

  10. Hashmap in java

    1. HashMap要点: 1.1 基本数据结构:  采用 数组+链表/平衡二叉查找树 的组合形式,所有键值对都以Entry<K,V>形式存储(每put进一个键值对,就会实例化一个Entr ...