POJ 2912 Rochambeau 【种类并查集】

题目来源:http://poj.org/problem?id=2912
在这里插入图片描述
在这里插入图片描述

★好久没写题了,又回到了并查集,发现并查集都没学好,写个锤子线段树


翻译:

有一群孩子在玩剪刀石头布游戏(真的是没看到剪刀石头布 半天不会写,一看到就明白了一二分)
一个人是裁判,其他的分为三组(可能有些组没人)
除了裁判可以变换着出,其他人都只能出固定的,并且同组的人是平局
然后给出m组胜负结果,让你判断能不能找到裁判


思路:

这题n和m的数量都不大,所以可以枚举哪个人是裁判来判断。
但是怎么处理人之间的关系呢?这里就用到了种类并查集~
我们不妨设
a>b 为 r=2
a<b 为r=1
a=b 为r=0

不难看出 a>b b>c 时 c>a 如果关系运算就是(2+2)%3=1 那么我们的定义就没问题

合并操作

在这里插入图片描述
a的父节点为p,b的父节点为q,a和p的关系式va,b和q的关系式vb,并且a和b的关系式r
那么把他们看作向量可知:va+vp-vb=r 故vp=(vb+r-va+3)%3
val[p]=(val[f[j].t]+f[j].r-val[f[j].s]+3)%3;
路径压缩就不说了~

代码:

#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<string>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
using namespace std;
const int maxn=5e2+5;
const int sz=1<<10;
const int mod=1e9+7;
const int inf=2e9;
const double eps=1e-8;
const double pi=acos(-1);
typedef long long LL;
int n,m;
char s[120];
struct node
{
    int s,t;
    int r;
}f[maxn<<3];
int dad[maxn];
int val[maxn];
template<class t>
inline void read(t &x)
{
    char c; x=1;
    while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
    t res=c-'0';
    while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
    x*=res;
}
int seek(int k)
{
    if(k==dad[k]) return k;
    int tmp=seek(dad[k]);
    val[k]=(val[k]+val[dad[k]])%3;
    return dad[k]=tmp;
}
int main()
{
    while(~scanf("%d%d",&n,&m)){
        getchar();
        for(int i=1;i<=m;i++){
            gets(s);
            int mid,len=strlen(s);
            for(int j=0;j<len;j++){
                if(s[j]=='>'||s[j]=='<'||s[j]=='='){
                    mid=j;
                    break;
                }
            }
            f[i].s=f[i].t=0;
            for(int j=0;j<mid;j++){
                f[i].s=f[i].s*10+s[j]-'0';
            }
            for(int j=mid+1;j<len;j++){
                f[i].t=f[i].t*10+s[j]-'0';
            }

            f[i].s++; f[i].t++;
            if(s[mid]=='>') f[i].r=2;
            else if(s[mid]=='<') f[i].r=1;
            else f[i].r=0;
//            cout<<f[i].s<<' '<<f[i].t<<' '<<f[i].r<<endl;
        }
        for(int i=1;i<=m;i++){
//            cout<<f[i].s<<' '<<f[i].t<<' '<<f[i].r<<endl;
        }
        int cnt=0;
        int round=0,who;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                dad[j]=j;
                val[j]=0;
            }
            int flag=-1;
            for(int j=1;j<=m;j++){
                if(f[j].s==i||f[j].t==i) continue;
                int p=seek(f[j].s),q=seek(f[j].t);
                if(p==q){
                    if((val[f[j].s]-val[f[j].t]+3)%3!=f[j].r){
                        flag=j;
                        break;
                    }
                }
                else{
                    dad[p]=q;
                    val[p]=(val[f[j].t]+f[j].r-val[f[j].s]+3)%3;
                }
            }
            if(flag==-1){
                cnt++;
                who=i-1;
            }
            else round=max(round,flag);
        }
        if(cnt==0) cout<<"Impossible\n";
        else if(cnt==1) printf("Player %d can be determined to be the judge after %d lines\n",who,round);
        else cout<<"Can not determine\n";
    }
    return 0;
}

发布了71 篇原创文章 · 获赞 89 · 访问量 8545

猜你喜欢

转载自blog.csdn.net/weixin_43890662/article/details/102589669