poj2912(带权并查集+枚举)

时间:2023-03-09 03:41:38
poj2912(带权并查集+枚举)

题目链接:http://poj.org/problem?id=2912

题意:给n个人,m组关系,玩石头剪刀布的游戏,n个人中除一个人judge以外,其他人属于3个group(即石头、剪刀、布),他们只能出这一个手势,而judge可以随便出,要求能否找到judge和在第几组关系时能最先找到judge。

思路:poj1182食物链的进阶版,与那题不同的是,这里需要枚举0到n-1,枚举i假设其为judge,然后遍历不包含i的所有关系,如果符合条件,则i就是judge,否则其不是judge,记录其判断出不是judge的那条边line(后面要用),遍历结束之后,如果judge数目num<1,则Impossible,若num>1,则Can not determine,若num=1,则其为judge,但需要输出判断其为judge的最小的line,其实也就是其它非judge判断为非judge的边line的最大值,这里有点巧妙。

   其余的就和食物链一样了,x->y=-1(<),0(=),1(>),且 x->z=(x->y+y->z+4)%3-1,公式自己手动算一下就明白了。

AC代码:

 #include<cstdio>
#include<cstring>
using namespace std; struct node{
int x,y;
char c;
}a[]; int n,m,root[],f[],ans[],res,num; int getr(int k){
if(root[k]==k) return k;
else{
int tmp=root[k];
root[k]=getr(root[k]);
f[k]=(f[k]+f[tmp]+)%-;
return root[k];
}
} int main(){
while(~scanf("%d%d",&n,&m)){
if(!m){
if(n==)
printf("Player 0 can be determined to be the judge after 0 lines\n");
else
printf("Can not determine");
continue;
}
memset(ans,,sizeof(ans));
num=;
for(int i=;i<=m;++i)
scanf("%d%c%d",&a[i].x,&a[i].c,&a[i].y);
for(int i=;i<n;++i){
bool flag=true;
for(int j=;j<n;++j)
root[j]=j,f[j]=;
for(int j=;j<=m;++j){
if(a[j].x!=i&&a[j].y!=i){
int t1=a[j].x,t2=a[j].y,t3,r1,r2;
if(a[j].c=='<') t3=-;
else if(a[j].c=='=') t3=;
else t3=;
r1=getr(t1),r2=getr(t2);
if(r1==r2){
if(f[t1]!=(t3+f[t2]+)%-){
ans[i]=j;
flag=false;
break;
}
}
else{
root[r2]=r1;
f[r2]=(-((t3+f[t2]+)%-)+f[t1]+)%-;
}
}
}
if(flag)
++num,res=i;
}
if(num<)
printf("Impossible\n");
else if(num>)
printf("Can not determine\n");
else{
int Max=;
for(int i=;i<n;++i)
if(ans[i]>Max)
Max=ans[i];
printf("Player %d can be determined to be the judge after %d lines\n",res,Max);
}
}
return ;
}