下面的是从该网站上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. 杭电ACM2097--Sky数

    这题思路很简单,把10,12,16进制数都按位相加,然后进行比较即可. http://acm.hdu.edu.cn/showproblem.php?pid=2097 <span style=&q ...

  2. 1 . Robberies (hdu 2955)

    The aspiring Roy the Robber has seen a lot of American movies, and knows that the bad guys usually g ...

  3. 2_1我的第一个应用hello world[wp8特色开发与编程技巧]

    2_1hello world -5min 大家好,我是徐文康,在上一个视频当中我们已经讲了,如何根据自己电脑系统去下载相应的SDK. 你可能花了很多时间去安装以及配置好了这个开发环境,如果还没有配置好 ...

  4. 信号处理程序(signal handler)会被重置的信号

    首先说明我的系统,CentOS 6.6,内核为2.6.32-504.12.2.el6.i686. 当用signal对某个信号设定信号处理函数的时候,有些信号的处理函数会被重置,有些则不会,这种情况的具 ...

  5. PHP获取和操作配置文件php.ini的几个函数

    当无法修改php.ini配置文件怎么办,莫担心. php有一套设置和获取配置信息的函数. 1.ini_get()获取配置参数,ini_set()设置配置参数 <?php

  6. mysql手工注入

    以下是mynona本人原创的,奉献给大家,不要小看数据库注入 参考: http://www.daydaydata.com/help/sql/advance/limit.html http://www. ...

  7. STM32调试大法 之 串口通讯

    开发过程经常需要查看某些特定参数.通常的方法可以使用paintf进行打印输出,观察具体的变量值.STM32内部集成有USART的串口功能,可以通过串口直接输出到电脑(上位机).使用非常方便,基本不需要 ...

  8. C#实现发送邮件——核心部分代码

    在KS系统中有个发送邮件的功能需要做上网查阅资料以后,通过自己的部分修改实现了发送邮件的功能话不多说先来个界面: 邮件发送分一下步骤: 1.smtp服务信息设置 2.验证发件人信息 3.添加附件 4. ...

  9. c# 空接合(??)运算符的运用

    相信很多人都看到??运算符,但是不一定每个人都知道它是用来做什么的,之前我也看到过很多次,但是因为一直没有去用过,所以也没有了解他的作用,今天又看到了,所以查了的MSDN,原来??运算符叫做空接合运算 ...

  10. python命令行参数处理模块 optparse 使用参考

    from optparse import OptionParser parser = OptionParser() parser.add_option( '-f', '--file', dest='f ...