poj 1733 Parity game (并查集+向量偏移)

/*
    并查集的向量偏移。把并查集看作是一片森林不断合并的过程。
    用map实现hash来对数据进行离散化
    rank[i]表示i到当前根节点的区间中的1的个数是奇数还是偶数(father[i],i]。1表示技术,0表示偶数。
    这块用到前缀的思想。
    要注意的是,对区间合并边界的处理。
    加入第i位到第j位为偶数个1,那么第1位到第i-1位和第1位到第j位1的个数同奇同偶
    如果为奇数个1,那么第1位到第i-1位和第1位到第j位1的个数互异,即一个为奇,一个为偶。
*/
#include<iostream>
#include<stdio.h>
#include<map>
using namespace std;
const int N = 10010;

int father[N];

int rank[N];

map<int,int>hash;

void InitSet()
{
    for(int i = 0 ; i < N ; i++)
    {
        father[i] = i;
        rank[i] = 0;
    }
}

int FindSet(int a)
{
    if(a != father[a])
    {
        int t = father[a];
        father[a] = FindSet(father[a]);
        rank[a] = (rank[a] + rank[t])%2;
    }
    return father[a];
}


void UnionSet(int a,int b,int d)
{
    int x = FindSet(a);
    int y = FindSet(b);
    father[x] = y;
    rank[x] = (rank[a] + rank[b] + d)%2;
}

int main()
{
    int n,m;
    int add = 0;
    int i;
    scanf("%d %d",&n,&m);
    InitSet();
    int cnt = 0;
    for( i = 0 ; i < m ; i++)
    {
        int a,b,d;
        char s[10];
        scanf("%d %d %s",&a,&b,s);
        a--;
        cnt++;
        if(hash.find(a) == hash.end())hash[a] = add++;
        int x = hash[a];
        if(hash.find(b) == hash.end())hash[b] = add++;
        int y = hash[b];
        int xx = FindSet(x);
        int yy = FindSet(y);
        if(s[0] == 'o')
        {
            d = 1;
        }
        else
        {
            d = 0;
        }
        if(xx == yy)
        {
            if((rank[x] + rank[y] + d )%2 != 0)
            {
                break;
            }
        }
        else
        {
            UnionSet(x,y,d);
        }
    }
    printf("%d\n",i);
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值