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