题意:多个人玩石头剪刀布,每个人提前选定了自己出哪个手势,而其中有一种特殊的人他可以随意出什么手势,问是否能够从给出的一系列石头剪刀布游戏中判断出哪个是特殊的,可以从第几局游戏中判断出来。
首先按照食物链那题的做法,定 0,1,2 做为三种手势就可以了,但是这题非常坑,如果在前面的游戏中就能够判断特殊的人了,那么之后的游戏就算有其他矛盾发生也不管了,所以只能找到错就跳出……不过由于判断是哪个人比较麻烦,不知道哪个人的选择是无效的,就不知道那几次游戏是不正确不能加入并查集的,因此就直接暴力枚举每个人是否为特殊的人,对于涉及这个人的所有游戏都不进行并查集操作,看剩下的游戏中是否会有矛盾,如果有就说明这个人不是特殊的人,否则他就可能是。最后如果只有一个人可能是,就可以判读出来,而判断出来的局数,就是枚举其他所有人出现矛盾的游戏场次的最大值,因为只有否定完其他所有人才能确定这个人是特殊的。
1 #include<stdio.h> 2 #include<string.h> 3 const int maxm=505; 4 5 int fa[maxm],num[maxm],wa[maxm]; 6 struct ques{ 7 int a,b,c; 8 }q[2005]; 9 10 void init(int n){ 11 for(int i=0;i<=n;++i){ 12 fa[i]=i; 13 num[i]=0; 14 } 15 } 16 17 int find(int x){ 18 int r=x,t1,t2,c=0; 19 while(r!=fa[r]){ 20 c+=num[r]; 21 r=fa[r]; 22 } 23 while(x!=r){ 24 t1=fa[x]; 25 t2=c-num[x]; 26 num[x]=c%3; 27 fa[x]=r; 28 c=t2; 29 x=t1; 30 } 31 return r; 32 } 33 34 int main(){ 35 int n,m; 36 while(scanf("%d%d",&n,&m)!=EOF){ 37 for(int i=1;i<=m;++i){ 38 char c; 39 scanf("%d",&q[i].a); 40 c=getchar(); 41 while(c!=‘=‘&&c!=‘<‘&&c!=‘>‘)c=getchar(); 42 if(c==‘=‘)q[i].c=0; 43 else if(c==‘<‘)q[i].c=1; 44 else if(c==‘>‘)q[i].c=2; 45 scanf("%d",&q[i].b); 46 } 47 memset(wa,-1,sizeof(wa)); 48 for(int i=0;i<n;++i){ 49 init(n); 50 for(int j=1;j<=m;++j){ 51 if(q[j].a==i||q[j].b==i)continue; 52 int x=find(q[j].a),y=find(q[j].b); 53 if(x!=y){ 54 fa[x]=y; 55 num[x]=((num[q[j].b]+q[j].c-num[q[j].a])%3+3)%3; 56 } 57 else{ 58 if((num[q[j].b]+q[j].c)%3!=num[q[j].a]){wa[i]=j;break;} 59 } 60 } 61 } 62 int cnt=0,ans1,ans2=0; 63 for(int i=0;i<n;++i){ 64 if(wa[i]==-1){ 65 cnt++; 66 ans1=i; 67 } 68 if(wa[i]>ans2)ans2=wa[i]; 69 } 70 if(!cnt)printf("Impossible\n"); 71 else if(cnt>1)printf("Can not determine\n"); 72 else printf("Player %d can be determined to be the judge after %d lines\n",ans1,ans2); 73 } 74 return 0; 75 }
时间: 2024-12-14 14:05:08