题意:多个人玩石头剪刀布,每个人提前选定了自己出哪个手势,而其中有一种特殊的人他可以随意出什么手势,问是否能够从给出的一系列石头剪刀布游戏中判断出哪个是特殊的,可以从第几局游戏中判断出来。
定义0, 1, 2为三种手势,枚举每一个人,对于这个人不进行并查集操作,看剩下的会不会有矛盾,没有的话就可能是。局数就是枚举其他所有人出现矛盾的游戏场次的最大值,因为只有否定完其他所有人才能确定这个人是特殊的。
注意输入那个字符。。。。。。
链接:poj 2912
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <limits>
#include <vector>
#include <sstream>
#define ll long long
using namespace std;
const int maxn = 2000 + 10;
const int maxm = 1000000 + 10;
const int inf = 0x3f3f3f3f;
int fa[maxn];
int r[maxn];
int error[maxn];
int n, m, k;
struct node {
int a, b, c;
}q[maxn];
void init() {
for(int i = 0; i < n; i++) {
fa[i] = i;
r[i] = 0;
}
}
int getf(int x) {
if(x != fa[x]) {
int rt = fa[x];
fa[x] = getf(fa[x]);
r[x] = (r[x] + r[rt]) % 3;
}
return fa[x];
}
int main()
{
int kcase = 0;
int T;
int a, b;
init();
int flag = 1;
while(~scanf("%d %d", &n, &m)) {
char c;
for(int i = 0; i < m; i++) {
scanf("%d", &q[i].a);
c = getchar();
while(c != '=' && c != '<' && c != '>') c = getchar();
if(c == '=') q[i].c = 0;
else if(c == '<') q[i].c = 1;
else q[i].c = 2;
scanf("%d", &q[i].b);
}
/*for(int i = 0; i < m; i++) {
printf("%d %d %d\n", q[i].a, q[i].c, q[i].b);
}*/
memset(error, -1, sizeof(error));
for(int i = 0; i < n; i++) {
init();
for(int j = 0; j < m; j++) {
if(q[j].a == i || q[j].b == i) continue;
int ra = getf(q[j].a);
int rb = getf(q[j].b);
if(ra == rb) {
if(r[q[j].b] != (r[q[j].a] + q[j].c) % 3) {
error[i] = j + 1;
break;
}
}
else {
fa[rb] = ra;
r[rb] = ((r[q[j].a] + q[j].c - r[q[j].b]) % 3 + 3) % 3;
}
}
}
int cnt = 0;
int a1, a2 = 0;
for(int i = 0; i < n; i++) {
if(error[i] == -1) {
cnt++;
a1 = i;
}
if(error[i] > a2) a2 = error[i];
}
if(!cnt) printf("Impossible\n");
else if(cnt > 1) printf("Can not determine\n");
else printf("Player %d can be determined to be the judge after %d lines\n", a1, a2);
}
return 0;
}