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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章