题意:有一些人玩石头剪刀布,其中有一个人(称其为裁判)可以出“石头”,“剪刀”,“布”中的任意一个,其他人永远只能出相同的一个。即有的人只能出剪刀,有的人只能出石头,有的人只能出布。进行了多次对决,每次只告诉你谁赢了(或者平手),不说谁出了什么。问能否判断出谁是裁判,裁判有多少个?若只有一个裁判,问在进行了多少次对决以后就能判断出裁判是谁。
解法:首先,判断出裁判的方法是,若1,2,3号选手的结果出现了矛盾,则1,2,3号中必有一个人是裁判,
(1)这个时候如果3,4号的对决结果出现矛盾,则判定3为裁判,然后还需要验证(即如果3为裁判,其他对决结果是不是不会有矛盾);
(2)这个时候如果4,5号出现矛盾,则说明裁判不止一个人,与题设不符;
(3)如果之后都再也没有出现矛盾,则说明不能判断出裁判是谁。
所以,方法就是,枚举谁是裁判,判断是否所有不涉及到裁判的对决结果之间没有矛盾。如果只有一个裁判,还需要求进行了多少次对决以后就已经能判断出裁判是谁了。由以上结论不难看出,在整个枚举过程中,最大的出现矛盾的对决的编号数即为所求。
tag:并查集,good
1 /* 2 * Author: Plumrain 3 * Created Time: 2013-11-28 19:23 4 * File Name: DS-POJ-2912.cpp 5 */ 6 #include <iostream> 7 #include <cstdio> 8 #include <vector> 9 10 using namespace std; 11 12 #define PB push_back 13 14 struct node{ 15 int f, r; 16 }; 17 18 int n, m, line; 19 node p[505]; 20 char xn[2005]; 21 vector<int> ans; 22 int an[2005], bn[2005]; 23 24 int find (int x) 25 { 26 if (x != p[x].f){ 27 int y = p[x].f; 28 p[x].f = find(y); 29 p[x].r = (p[x].r + p[y].r) % 3; 30 } 31 return p[x].f; 32 } 33 34 void merge(int a, int b, char xx, int t1, int t2) 35 { 36 int x; 37 if (xx == '=') x = 0; 38 else if (xx == '>') x = 1; 39 else x = 2; 40 41 p[t1].f = t2; 42 p[t1].r = (3 - p[a].r + x + p[b].r) % 3; 43 } 44 45 bool ok(int a, int b, char xx) 46 { 47 int x; 48 if (xx == '=') x = 0; 49 else if (xx == '>') x = 1; 50 else x = 2; 51 52 return x == ((p[a].r + 3 - p[b].r) % 3); 53 } 54 55 bool gao(int x) 56 { 57 for (int i = 0; i < n; ++ i){ 58 p[i].f = i; 59 p[i].r = 0; 60 } 61 62 for (int i = 0; i < m; ++ i){ 63 if (an[i] == x || bn[i] == x) continue; 64 65 int t1 = find(an[i]), t2 = find(bn[i]); 66 if (t1 != t2) 67 merge(an[i], bn[i], xn[i], t1, t2); 68 if (t1 == t2) 69 if (!ok(an[i], bn[i], xn[i])){ 70 line = max(line, i + 1); 71 return 0; 72 } 73 } 74 return 1; 75 } 76 77 int main() 78 { 79 while (scanf ("%d%d", &n, &m) != EOF){ 80 if (!m){ 81 if (n == 1) printf ("Player 0 can be determined to be the judge after 0 lines "); 82 else printf ("Can not determine "); 83 continue; 84 } 85 86 for (int i = 0; i < m; ++ i) 87 scanf ("%d%c%d", &an[i], &xn[i], &bn[i]); 88 89 ans.clear(); 90 line = 0; 91 for (int i = 0; i < n; ++ i) 92 if (gao(i)) ans.PB (i); 93 94 int sz = ans.size(); 95 if (sz > 1) printf ("Can not determine "); 96 else if (!sz) printf ("Impossible "); 97 else printf ("Player %d can be determined to be the judge after %d lines ", ans[0], line); 98 } 99 return 0; 100 }