POJ 2912 Rochambeau
題目鏈接:vjudge傳送門
題目大意:
給定n個孩子,編號[0,n),以及m組兩人剪刀石頭布的結果,n個人中有一個孩子是裁判,剩餘的人被分成3組,通一組人出同一個手勢,裁判也參與見到石頭布遊戲,只不過有它的那組結果是隨機給的(即正確與否不保證),問能否判斷出哪個孩子是裁判,若可以求出最少需要前多少條語句可以判斷出。
具體思路:
帶權並查集,權值數組的維護與poj1182食物鏈這一題是一樣的,沒做過的可以先去看一下,這是題解
關於枚舉操作:
依次假設每個孩子爲裁判,然後通過m組關係判斷該孩子是否爲裁判(有作爲裁判的孩子參與的忽略),若不是則記錄在第幾條語句發生衝突。
經過N輪枚舉,能得出總共有cnt個孩子可以當裁判
若
- cnt=0,說明 Impossible
- X>1,說明Can not determine
- X==1時,輸出那個作爲裁判孩子的編號,且輸出其他所有小孩中發生衝突語句的 最大值max,即通過前max條語句我們就能知道N-1個小孩都不可能是裁判
參考:https://blog.csdn.net/u013480600/article/details/21198751
具體代碼:
#include <cstdio>
#include<cstring>
using namespace std;
const int N = 505,M=2005;
int fa[N], ral[N];
int isNotJudge[N], sentence[N]; //是否是裁判,以及不是裁判是發生矛盾的語句是第幾條
struct Node {
int u, v, r;
void setNode(int u, int v, char op) {
this->u = u, this->v = v;
if (op == '>')r = 1;
else if (op == '<')r = 2;
else r = 0;
}
}round[M];
void init(int n)
{
for (int i = 0; i < n; i++)
{
fa[i] = i;
ral[i] = 0;
}
}
int find(int son)
{
if (son == fa[son])
return son;
int root = fa[son];
fa[son] = find(fa[son]);
ral[son] = (ral[son] + ral[root]) % 3;
return fa[son];
}
void Unite(int x, int y, int d)
{
int fx = find(x);
int fy = find(y);
fa[fy] = fx;
ral[fy] = (3 - ral[y] + d + ral[x]) % 3;
}
int main()
{
int n,m;
while (~scanf("%d%d", &n, &m))
{
for (int i = 0; i < m; i++)
{
int u, v;
char op;
scanf("%d %c %d", &u,&op,&v);
round[i].setNode(u, v, op);
}
memset(isNotJudge, 0, sizeof(isNotJudge));
memset(sentence, 0, sizeof(sentence));
for (int i = 0; i < n; i++) //枚舉裁判
{
init(n); //每次枚舉都要初始化並查集,一開始把他放枚舉裁判循環外了
for (int j = 0; j < m; j++)
{
int u = round[j].u, v = round[j].v, r = 3 - round[j].r; //3-r纔是v->u的關係
if (u == i || v == i)continue; //跳過裁判的話
if (find(u) == find(v)) {
if ((ral[u] + r) % 3 != ral[v]) {
isNotJudge[i] = 1;
sentence[i] = j + 1; //記錄下第幾條語句發現錯誤
break;
}
}
else Unite(u, v, r);
}
}
int cnt = 0, jud, num = 0;
for (int i = 0; i < n; i++)
{
if (sentence[i] > sentence[num])num = i; //發現關係矛盾,需要最多的語句
if (!isNotJudge[i]) {
cnt++; //記錄滿足裁判的個數
jud = i; //當只有一個裁判時,需要輸出
}
}
if(cnt==0)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", jud, sentence[num]);
}
return 0;
}