暑期前专题题解---数据结构---J

        并查集的一个好题目,因为石头剪刀布的三角关系,我们可以用0表示两个同类,1表示被它的父亲克制,2表示克制它的父亲,那么一个节点和爷爷节点的关系就变成了,(re[x] + re[pre[x] ])  % 3 ,因为并查集带压缩路径,所以最后join时,最多存在一个四边形的关系,讨论x和y的根节点是否相同即可。

代码如下

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 10;
int pre[maxn],re[maxn];
int n,m,opt,x,y,cnt,tag;
void init(int n){
    for (int i=0; i<=n; i++) {
        pre[i] = i;
    }
}
int find(int x){
    if (pre[x] == x) return x;
    int fx = find(pre[x]);
    re[x] = (re[pre[x]]+re[x]) % 3;
    pre[x] = fx;
    return fx;
}
void join(int x,int y,int opt){
    int fx = find(x),fy = find(y);
    if (opt == 1) opt--;
    if (fx != fy){
        pre[fx] = fy;
        re[fx] = ((opt + re[y]) % 3 + (3 - re[x]) % 3) % 3;
     }else{
        if (opt != (re[x] + (3 - re[y]) % 3) % 3 && tag != 1){
            cout << cnt << endl; tag = 1;
        }
    }
}

int main(){
    cin >> n >> m;
    init(n);
    for (int i=0; i<m; i++) {
        scanf("%d%d%d",&opt,&x,&y);
        cnt++;
        if (opt == 1){
            join(x, y, opt);
        }else if (opt == 2){
            join(x, y, opt);
        }
        if(cnt == 3) cnt = 0;
       // cout << re[x] << endl;
    }
    if (!tag) cout << -1 << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/CCCCTong/article/details/81413707