并查集-POJ1733Parity game
http://poj.org/problem?id=1733
首先感谢一下poj,讨论里面数据都有;
全英文题目根本无版权问题
不像某谷省选题数据不给的;
这道题就是并查集;
给你x,y的区间,让这个区间1的数量是奇数偶数;
这道题目我做了大约两个小时;
唉~~~~
但是毕竟是自己做出来的;
我们并查集,可以记录1~x的数的奇偶性;
然后就用拆点嘛,和监狱那题差不多;
然后就没了;
……………
当然我也算是从最原始的并查集里面走出来了;
不是拆点嘛;
我一开始拆成偶数奇数,然后就下不去了;
后来才想到要拆成相同不相同;
显然把,相同不相同才可以把题目转换成集合;
而偶数奇数只有两个集合;
离散就不讲了;
自己搞吧;
反正因为我的并查集记录的是1~x的区间;
所以我们对于一个区间x,y要算1~x-1,1~y两个区间;
呵呵呵呵,所以离散就要判断两个数是否相差1;
当然,建议大家把最小的值设为2而不是1;
为什么?
看我程序把,我是设为1 的;
#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
struct cs{
int x,y,z;
}F[1000001];
int fa[1000001],c[100001][5];
int ff,n,m,x,y,z,nn,xx,yy,xxx,yyy;
string s;
bool cmp(cs x,cs y){return x.z<y.z;}
int get(int x){
if(fa[x]==x)return x;
fa[x]=get(fa[x]);
return fa[x];
}
void merge(int x,int y){fa[get(x)]=get(y);}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d",&x,&y);
cin>>s;
c[i][1]=x;
c[i][2]=y;
if(s=="odd")c[i][3]=1;
F[++ff].z=x;F[ff].x=i;F[ff].y=1;
F[++ff].z=y;F[ff].x=i;F[ff].y=2;
}
sort(F+1,F+ff+1,cmp);
for(int i=1;i<=ff;i++){
if(F[i].z!=F[i-1].z){
nn++;
if(F[i].z!=F[i-1].z+1)nn++;//离散要保证区间的准确
}
c[F[i].x][F[i].y]=nn;
}
// for(int i=1;i<=m;i++)cout<<c[i][1]<<' '<<c[i][2]<<endl;
for(int i=1;i<=nn*2+2;i++)fa[i]=i;
for(int i=1;i<=m;i++){
x=c[i][1];
y=c[i][2];
z=c[i][3];
xx=get(x-1);
yy=get(y);
xxx=get(x-1+nn+1);
//因为我把最小值设成1,所以x=1时会取到x-1=0;0+nn=nn;所以0和nn会重复!!!!所以我们把区间大小+1,即nn+1;
yyy=get(y+nn+1);
if(z)if(xx==yy||xxx==yyy){printf("%d",i-1);return 0;}else merge(xxx,yy),merge(yyy,xx);
if(!z)if(xx==yyy||yy==xxx){printf("%d",i-1);return 0;}else merge(xx,yy),merge(xxx,yyy);
}
printf("%d",m);
}