Parity game POJ - 1733

权值并查集

(x,y)(y,z)(x,z)
000
011
101
110

显然是异或关系

#include<cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <vector>
using namespace std;
#define fst first
#define sec second
#define sci(num) scanf("%d",&num)
#define scl(num) scanf("%lld",&num)
#define mem(a,b) memset(a,b,sizeof a)
#define cpy(a,b) memcopy(a,b,sizeof b)
typedef long long LL;
typedef pair<int,int> P;
const int MAX_N = 10010;
const int MAX_M = 10000;
struct Iter{
    int l,r,f;
} iter[MAX_N];
int locs[MAX_N],loc = 0;
int Fa[MAX_N],R[MAX_N],N,M,Q;
void init() {
    for (int i = 0;i < MAX_N;i++) {
        Fa[i] = i;
        R[i] = 0;
    }
}
int Find(int x) {
    if (Fa[x] != x) {
        int p = Fa[x];
        Fa[x] = Find(Fa[x]);
        R[x] = R[x] ^ R[p];
    }
    return Fa[x];
}
int main() {
    sci(M);
    sci(Q);
    for (int i = 0;i < Q;i++) {
        char str[10];
        scanf("%d%d%s",&iter[i].l,&iter[i].r,str);
        iter[i].l--;
        locs[loc++] = iter[i].l;
        locs[loc++] = iter[i].r;
        if (str[0] == 'o') {
            iter[i].f = 1;
        } else {
            iter[i].f = 0;
        }
    }
    init();
    sort(locs,locs+loc);
    loc = unique(locs,locs+loc) - locs;
    for (int i = 0;i < Q;i++) {
        int loc1 = lower_bound(locs,locs+loc,iter[i].l) - locs;
        int loc2 = lower_bound(locs,locs+loc,iter[i].r) - locs;
        int lf = Find(loc1);
        int rf = Find(loc2);
        if (lf == rf) {	//判断是否在一个集合
            if (iter[i].f != (R[loc1] ^ R[loc2])) { //此时R已经表示为与父亲节点关系,判断其对应关系是否满足iter[i]^f
                printf("%d\n",i);
                return 0;
            }
        } else {
            Fa[lf] = rf; 
            //已经知道 (loc1,lf) (loc2,rf) 求(lf,rf)
            // (loc1,lf) ^ (lf,rf) == R(loc1,loc2) ^ (loc2,rf)
            if (iter[i].f == 0) { // 
                R[lf] = R[loc1] ^ R[loc2];
            } else {
                R[lf] = R[loc1] ^ R[loc2] ^ iter[i].f;
            }
        }
    }
    printf("%d\n",Q);
    return 0;
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值