您的位置:首页 > 其它

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

2013-11-29 23:22 309 查看
/*
并查集的向量偏移。把并查集看作是一片森林不断合并的过程。
用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
;

int rank
;

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: