Rochambeau ——带权并查集
作者:互联网
题意:
石头剪刀布,有一个人时裁判,给你一系列情况,让你判断裁判的情况:
有一个裁判-------player x can be determined to be the judge after y lines
没有裁判,谁是裁判都不成立-------Impossible
有多个裁判-------Can not determine
“裁判”的意思是,比如0是裁判,则去掉含有0的行,剩下的行成立。
题解:
做法类似食物链题目
u=v 记为 0
u<v 记为 1
u>v 记为 2
因为数据范围不大,所以枚举每一个人是否为裁判,对于枚举的人,不进行并查集操作,看剩下的游戏中是否会有矛盾
如果有矛盾,则说明这个人不是裁判,并且记录那个回合出现矛盾,否则他就可能是裁判
然后就遍历所有人看是否只有一个人没有出现矛盾,如果只有一个,则说明可以确定裁判,那么确定裁判的局数就是其他人出现矛盾的回合的最大值。因为只有否定了其他所有人,才能够确定才裁判。
代码:
#include<iostream> #include<stdio.h> #include<math.h> #include<cstring> using namespace std; typedef long long ll; const int maxn=2e5+5; int d[maxn]; int f[maxn]; int ans[maxn]; int n,m; struct node { int u,v; int r; } a[maxn]; int Find(int x) { if(x==f[x])return x; int root=Find(f[x]); d[x]=(d[x]+d[f[x]])%3; return f[x]=root; } void init() { for(int i=0; i<=n; i++)f[i]=i,d[i]=0; } int main() { while(~scanf("%d%d",&n,&m)) { for(int i=1;i<=m;i++) { char op; scanf("%d%c%d",&a[i].u,&op,&a[i].v); if(op=='=')a[i].r=0; else if(op=='<')a[i].r=1; else a[i].r=2; } memset(ans,-1,sizeof ans); for(int i=0;i<n;i++) { init(); for(int j=1;j<=m;j++) { if(i==a[j].u || i==a[j].v)continue; int fx=Find(a[j].u); int fy=Find(a[j].v); if(fx==fy) { if((d[a[j].v]-d[a[j].u]+3)%3 != a[j].r) { ans[i]=j; break; } } else { f[fx]=fy; d[fx]=((d[a[j].v]-a[j].r-d[a[j].u]+3)%3+3)%3; } } } int cnt=0; int res1=0,res2=0; for(int i=0;i<n;i++) { if(ans[i]==-1) { cnt++; res1=i; } res2=max(res2,ans[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", res1, res2); } return 0; }View Code
标签:return,裁判,int,查集,Rochambeau,矛盾,带权,maxn,include 来源: https://www.cnblogs.com/j666/p/11614974.html