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


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