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