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;
}