poj2912 带权并查集

题意:多个人玩石头剪刀布,每个人提前选定了自己出哪个手势,而其中有一种特殊的人他可以随意出什么手势,问是否能够从给出的一系列石头剪刀布游戏中判断出哪个是特殊的,可以从第几局游戏中判断出来。

首先按照食物链那题的做法,定 0,1,2 做为三种手势就可以了,但是这题非常坑,如果在前面的游戏中就能够判断特殊的人了,那么之后的游戏就算有其他矛盾发生也不管了,所以只能找到错就跳出……不过由于判断是哪个人比较麻烦,不知道哪个人的选择是无效的,就不知道那几次游戏是不正确不能加入并查集的,因此就直接暴力枚举每个人是否为特殊的人,对于涉及这个人的所有游戏都不进行并查集操作,看剩下的游戏中是否会有矛盾,如果有就说明这个人不是特殊的人,否则他就可能是。最后如果只有一个人可能是,就可以判读出来,而判断出来的局数,就是枚举其他所有人出现矛盾的游戏场次的最大值,因为只有否定完其他所有人才能确定这个人是特殊的。

 1 #include<stdio.h>
 2 #include<string.h>
 3 const int maxm=505;
 4
 5 int fa[maxm],num[maxm],wa[maxm];
 6 struct ques{
 7     int a,b,c;
 8 }q[2005];
 9
10 void init(int n){
11     for(int i=0;i<=n;++i){
12         fa[i]=i;
13         num[i]=0;
14     }
15 }
16
17 int find(int x){
18     int r=x,t1,t2,c=0;
19     while(r!=fa[r]){
20         c+=num[r];
21         r=fa[r];
22     }
23     while(x!=r){
24         t1=fa[x];
25         t2=c-num[x];
26         num[x]=c%3;
27         fa[x]=r;
28         c=t2;
29         x=t1;
30     }
31     return r;
32 }
33
34 int main(){
35     int n,m;
36     while(scanf("%d%d",&n,&m)!=EOF){
37         for(int i=1;i<=m;++i){
38             char c;
39             scanf("%d",&q[i].a);
40             c=getchar();
41             while(c!=‘=‘&&c!=‘<‘&&c!=‘>‘)c=getchar();
42             if(c==‘=‘)q[i].c=0;
43             else if(c==‘<‘)q[i].c=1;
44             else if(c==‘>‘)q[i].c=2;
45             scanf("%d",&q[i].b);
46         }
47         memset(wa,-1,sizeof(wa));
48         for(int i=0;i<n;++i){
49             init(n);
50             for(int j=1;j<=m;++j){
51                 if(q[j].a==i||q[j].b==i)continue;
52                 int x=find(q[j].a),y=find(q[j].b);
53                 if(x!=y){
54                     fa[x]=y;
55                     num[x]=((num[q[j].b]+q[j].c-num[q[j].a])%3+3)%3;
56                 }
57                 else{
58                     if((num[q[j].b]+q[j].c)%3!=num[q[j].a]){wa[i]=j;break;}
59                 }
60             }
61         }
62         int cnt=0,ans1,ans2=0;
63         for(int i=0;i<n;++i){
64             if(wa[i]==-1){
65                 cnt++;
66                 ans1=i;
67             }
68             if(wa[i]>ans2)ans2=wa[i];
69         }
70         if(!cnt)printf("Impossible\n");
71         else if(cnt>1)printf("Can not determine\n");
72         else printf("Player %d can be determined to be the judge after %d lines\n",ans1,ans2);
73     }
74     return 0;
75 }

时间: 2024-12-14 14:05:08

poj2912 带权并查集的相关文章

并查集练习2(带权并查集)

明天旅游去爬山逛庙玩,今天练一天然后早早睡觉啦~ poj1703 Find them, Catch them (带权并查集) 1 #include<cstdio> 2 const int N=1e5+1; 3 int f[N]; 4 int r[N];//表示与父节点的关系,0同类,1不同类 5 int n; 6 void init(){ 7 for(int i=1;i<=n;++i){ 8 f[i]=i; r[i]=0; 9 } 10 } 11 int fin(int x){ 12 i

hdu3038(带权并查集)

题目链接: http://acm.split.hdu.edu.cn/showproblem.php?pid=3038 题意: n表示有一个长度为n的数组, 接下来有m行形如x, y, d的输入, 表示从第x,个元素到第y个元素的和为d(包括x, 和y), 问m行输入里面有几个是错误的(第一个输入是正确的); 思路: 很显然带权并查集咯,我们可以用距离的概念代替和的概念比较好理解一点,d表示x到y的和即x到y的距离; 可以用rank[x]表示x到其父亲节点的距离,  将正确的距离关系合并到并查集中

【POJ1182】 食物链 (带权并查集)

Description 动物王国中有三类动物A,B,C,这三类动物的食物链构成了有趣的环形.A吃B, B吃C,C吃A. 现有N个动物,以1-N编号.每个动物都是A,B,C中的一种,但是我们并不知道它到底是哪一种. 有人用两种说法对这N个动物所构成的食物链关系进行描述: 第一种说法是"1 X Y",表示X和Y是同类. 第二种说法是"2 X Y",表示X吃Y. 此人对N个动物,用上述两种说法,一句接一句地说出K句话,这K句话有的是真的,有的是假的.当一句话满足下列三条之

【poj 1988】Cube Stacking(图论--带权并查集 模版题)

题意:有N个方块,M个操作{“C x”:查询方块x上的方块数:“M x y”:移动方块x所在的整个方块堆到方块y所在的整个方块堆之上}.输出相应的答案. 解法:带权并查集.每堆方块作为一个集合,维护3个数组:fa[x]表示x方块所在堆的最顶部的方块:d[x]表示x方块所在堆的最底部的方块:f[x]表示x方块方块x上的方块数. 1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<

Lightoj1009 Back to Underworld(带权并查集)

转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud Back to Underworld Time Limit:4000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu Description The Vampires and Lykans are fighting each other to death. The war has become so fierc

[NOIP摸你赛]Hzwer的陨石(带权并查集)

题目描述: 经过不懈的努力,Hzwer召唤了很多陨石.已知Hzwer的地图上共有n个区域,且一开始的时候第i个陨石掉在了第i个区域.有电力喷射背包的ndsf很自豪,他认为搬陨石很容易,所以他将一些区域的陨石全搬到了另外一些区域. 在ndsf愉快的搬运过程中,Hzwer想知道一些陨石的信息.对于Hzwer询问的每个陨石i,你必须告诉他,在当前这个时候,i号陨石在所在区域x.x区域共有的陨石数y.以及i号陨石被搬运的次数z. 输入描述: 输入的第一行是一个正整数T.表示有多少组输入数据. 接下来共有

hdu 1558 Segment set【基础带权并查集+计算几何】

Segment set Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3599    Accepted Submission(s): 1346 Problem Description A segment and all segments which are connected with it compose a segment set

Corporative Network(带权并查集)

这个题的题意是  当输入'E'是查找操作,查找从后面这个数到他的父亲这边的值,'I'代表把后面的数作为前面数的父亲 然后他们两个的差值代表这两个边的权值 水水的题 #include <stdio.h> #include <string.h> int par[20005]; int rank1[20005]; int abs(int hh) { return (hh>0)?hh:-hh; } void init() { for(int i=0;i<20005;i++) {

POJ 1984 Navigation Nightmare 二维带权并查集

题目来源:POJ 1984 Navigation Nightmare 题意:给你一颗树 k次询问 求2点之间的曼哈顿距离 并且要在只有开始k条边的情况下 思路:按照方向 我是以左上角为根 左上角为原点 dx[i]为i点距离根的x坐标 dy[]是y坐标 这两个可以通过路径压缩求出 只不过是二维而已 #include <cstdio> #include <cstdlib> #include <cstring> using namespace std; const int m