Rochambeau ——带权并查集
Posted j666
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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;
以上是关于Rochambeau ——带权并查集的主要内容,如果未能解决你的问题,请参考以下文章