[题解]POJ_2912_(带权并查集

前言:无主之地3优化堪忧,且价格偏高。想看新上映的柯南的电影

https://www.cnblogs.com/geloutingyu/p/6145706.html

题意为给定$n$个人玩剪刀石头布,给出$m$个输赢关系,其中除了一个裁判其他人都只会出一样的手势,问是否存在这样的裁判,若存在且能确定输出裁判编号和最少在第几轮确定,若不能确定是谁输出另外的字符串

维护关系使用并查集,但是对于裁判我们没法处理,如果先想简单版本没有裁判的话,我们无非是维护带边权/扩展域并查集看有没有冲突即可,结合数据范围,不如枚举裁判的编号,维护剩下人的关系,如果成立那么他可能是裁判

如果有多个符合条件的人那么我们无法判断是谁,根据样例也能看出来

最早判断出来的时间是其他$n-1$个人都被排除的时间,也就是这些有矛盾的关系中最晚的一个

具体边权之间的关系据说可以推出来(我没有

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
using namespace std;
const int maxn=509;
int n,m;
int fa[maxn],d[maxn];
inline int find(int x){
    if(x==fa[x])return x;
    int rt=find(fa[x]);
    d[x]=(d[x]+d[fa[x]])%3;
    return fa[x]=rt;
}
struct node{
    int a,b,c;
}q[2009];
bool pd(int a,int b,int c){
    int aa=find(a),bb=find(b);
    if(aa==bb){
//        if(d[a]==0){
//            if(d[b]!=c)return 1;
//        }
//        else if(d[a]==1){
//            if(abs(d[b]-1)!=c)return 1;
//        }
//        else{
//            if(abs(d[b]-2)!=c)return 1;
//        }
        if((d[b]-d[a]+3)%3!=c)return 1;
    }
    else {
        fa[bb]=aa;
//        if(d[a]==0)d[bb]=c;
//        else{
//            int fa=(d[a]+c)%3,fb=(d[b]+c)%3;
//            if(fa-fb==1)d[bb]=1;
//            else if(fa-fb==-1)d[bb]=2;
//            else d[bb]=0;
//        }
        d[bb]=(d[a]-d[b]+c+3)%3;
    }
    return 0;
}
int main(){
    while(~scanf("%d%d",&n,&m)){
        char c;
        for(int i=1;i<=m;i++){
            scanf("%d%c%d",&q[i].a,&c,&q[i].b);
            if(c=='=')q[i].c=0;
            else if(c=='>')q[i].c=1;
            else q[i].c=2;
        }
//        for(int i=1;i<=m;i++)cout<<q[i].c<<endl;
        int tot=0,flg=1,mx=0,jud=0;
        for(int i=0;i<n;i++){//枚举裁判 
            flg=1;
            for(int j=0;j<n;j++)d[j]=0,fa[j]=j;
            for(int j=1;j<=m;j++){
                if(q[j].a==i || q[j].b==i)continue;//排除裁判 
                if(pd(q[j].a,q[j].b,q[j].c)){
                    mx=max(j,mx);
                    flg=0;
                    break;
                }
            }
            if(flg){
                tot++;jud=i;
            }
        }
        if(!tot)printf("Impossible
");
        else if(tot>1)printf("Can not determine
");
        else printf("Player %d can be determined to be the judge after %d lines
",jud,mx);
    }
}
原文地址:https://www.cnblogs.com/superminivan/p/11544673.html