题目链接:Rochambeau
题意:一群孩子分成三组玩石头剪刀布,在某一组中的孩子只能出和其组对应的手势,其中有一个人是裁判,裁判可以任意出,问能否在给定的游戏场景中找到裁判并输出对应的信息。
题解:由于
N
<script type="math/tex" id="MathJax-Element-4">N</script>很小,所以直接枚举裁判,和裁判有关的场次直接忽略,那么就成了一个权值并查集。最后如果只有一个人满足条件,输出能排除其他情况的最小场次。
#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
const int N = 505*3;
int f[N];
int Find(int x){
int r=x;
while(f[x]!=x)
x=f[x];
f[r]=x;
return x;
}
void Merge(int x,int y){
x=Find(x);
y=Find(y);
if(x!=y)
f[x]=y;
}
struct RCB{
int x,y;
char op;
}r[2005];
int ans[505];
int main(){
int n,m;
while(scanf("%d %d",&n,&m)==2){
for(int i=1;i<=m;i++)
scanf("%d%c%d",&r[i].x,&r[i].op,&r[i].y);
memset(ans,-1,sizeof ans);
int cnt=0,mx=0,ps=0;
for(int i=0;i<n;i++){
for(int j=0;j<=3*n;j++)
f[j]=j;
for(int j=1;j<=m;j++)
if(r[j].x!=i&&r[j].y!=i){
if(r[j].op=='>'){
if(Find(r[j].x)==Find(r[j].y)||
Find(r[j].x+n)==Find(r[j].y)){
ans[i]=j;
break;
}
Merge(r[j].x,r[j].y+n);
Merge(r[j].x+n,r[j].y+2*n);
Merge(r[j].x+2*n,r[j].y);
}else if(r[j].op=='='){
if(Find(r[j].x)==Find(r[j].y+2*n)||
Find(r[j].x)==Find(r[j].y+n)){
ans[i]=j;
break;
}
Merge(r[j].x,r[j].y);
Merge(r[j].x+n,r[j].y+n);
Merge(r[j].x+2*n,r[j].y+2*n);
}else{
if(Find(r[j].x)==Find(r[j].y)||
Find(r[j].x)==Find(r[j].y+n)){
ans[i]=j;
break;
}
Merge(r[j].x,r[j].y+2*n);
Merge(r[j].x+n,r[j].y);
Merge(r[j].x+2*n,r[j].y+n);
}
}
cnt+=(ans[i]==-1?1:0);
ps=(ans[i]==-1?i:ps);
if(mx<ans[i])
mx=ans[i];
}
if(cnt==1)
printf("Player %d can be determined to be the judge after %d lines\n",ps,mx);
else if(cnt==0)
puts("Impossible");
else
puts("Can not determine");
}
return 0;
}