POJ 1733 Parity game

解题思路:hash离散化+并查集

首先我们不考虑离散化:s[x]表示(root[x],x]区间1的个数的奇偶性,0-偶数,1-奇数

每个输入区间[a,b],首先判断a-1与b的根节点是否相同

a)如果相同表示(a-1,b]之间1的个数奇偶性已知s((a-1,b])=s[a-1]^s[b],此时只需简单判断即可

b)如果不同,我们需要合并两个子树,我们将root较大的子树(例root[a])合并到root较小的子树(例root[b]),且此时s[root[a]]=s[a]^s[b]^s((a-1,b])

在路径压缩的过程中s[i]=s[i]^s[root[i]],s[root[i]]为(root[root[i]], root[i]]区间内1个数的奇偶性,例(a, b]区间1的个数为偶数,(b, c]区间1的个数为奇数,(a, c]之间1的个数显然为0^1=1奇数

欢迎review
 
   
#include < iostream >
using namespace std;
#define MOD 9941
#define MAX 10005

struct node
{
node():next(
0 ){}
int val, index;
node
* next;
}HashMap[MOD];

int root[MAX],num[MAX],u = 0 ;
char c[MAX];
int find( int x)
{
int y = x % MOD;
node
* p, * q;
p
= & HashMap[y], q = HashMap[y].next;
while (q)
if (q -> val == x) return q -> index;
else p = q,q = q -> next;
node
* temp = new node(); temp -> val = x,temp -> index =++ u,p -> next = temp,num[u] = x;
return u;
}
int findroot( int x)
{
int t;
if (root[x] != x){t = root[x];root[x] = findroot(root[x]);c[x] = c[t] ^ c[x];}
return root[x];
}
int main()
{
int i,l,n,s,t,r1,r2,v,ans;
bool IsError = false ;
char ch[ 5 ];
for (i = 0 ;i < MAX;i ++ )root[i] = i,c[i] = 0 ;
scanf(
" %d\n%d " , & l, & n);
for (i = 1 ; i <= n;i ++ )
{
scanf(
" %d %d %s " , & s, & t, ch);
if (IsError) continue ;
v
= (ch[ 0 ] == ' e ' ) ? 0 : 1 ;
s
= find(s - 1 ),t = find(t);
r1
= findroot(s), r2 = findroot(t);
if (r1 == r2 && (c[s] ^ c[t] ^ v)){IsError = true ;ans = i - 1 ;}
else if (r1 != r2)
{
if (num[r1] < num[r2])root[r2] = r1,c[r2] = c[s] ^ c[t] ^ v;
else root[r1] = r2, c[r1] = c[s] ^ c[t] ^ v;
}
}
IsError
? printf( " %d\n " ,ans) : printf( " %d\n " , n);
return 0 ;
}

 

转载于:https://www.cnblogs.com/ltang/archive/2010/12/07/1898919.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值