下面的是从该网站上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. 躲避球游戏ios源码

    躲避球游戏源码,有限源码是一个基于cocos2d的躲避球游戏源码的,并且还引用了大家熟悉google广告的,进行推广,已经还有带game center等,游戏操作很简单,用手指按住物体,然后移动物体避 ...

  2. .NET4.5可以给所有线程设置默认的Culture了

    How to set CurrentCulture for all threads in a domain in .NET 4.5 Before .NET 4.5 if we wanted to se ...

  3. DIV_ROUND_UP(x,y)实现x/y向上取整

    #define DIV_ROUND_UP(x,y) (((x) + ((y) - 1)) / (y)) 1.问题 x.y都是整数,且x > 1, y > 1,求 x / y的向上取整,即: ...

  4. Javascript this 解析

    Javascript中,this是一个非常有用的关键字, this是在运行时基于函数的运行环境绑定的,但是,如果使用的时候不注意,很容易就出错了. ECMAScript Standard对this的定 ...

  5. ios 控件

    反序列化 JSONModel 上拉刷新 下拉加载更多 MJRefresh AFNetworking 2.5 Asynchronous image downloader with cache - SDW ...

  6. JQ 选择器大全

    一.基本选择器 选择器 描 述 返回 示例 #id 根据给定id匹配一个元素 单个元素 $("#test") 选取id为test的元素 .class 根据给定类名匹配一个元素 集合 ...

  7. Android L Ripple的使用

    声明:Demo并不是有本人所写,本人只是总结在这里 工程源码: RippleDemo.zip ---------------------------------------------------- ...

  8. google查询技巧

    技巧一:使用正确的方法 无论你是使用一个简单或是高级的Google搜索,在此都存在你应该使用的某种可靠的方法.遵循适当的方法你就能获得非常准确的结果:要是忽略这条建议的话,你也许就会看到大量不相关的结 ...

  9. 【转】Eazfuscator.NET 3.3中混淆化需要注意的一些问题

    对于DLL,Eazfuscator.NET默认不会混淆化任何公共成员,因为类库的公共成员很有可能被外界调用,而对于EXE的程序集,所有类型都可能被混淆化.注意上面这句话有一个“可能”,因为Eazfus ...

  10. Redis 代理服务Twemproxy

    1.twemproxy explore 当我们有大量 Redis 或 Memcached 的时候,通常只能通过客户端的一些数据分配算法(比如一致性哈希),来实现集群存储的特性.虽然Redis 2.6版 ...