poj1733 Parity game[带权并查集or扩展域]
连通性判定问题。(具体参考lyd并查集专题该题的转化方法,反正我菜我没想出来)。转化后就是一个经典的并查集问题了。
带权:要求两点奇偶性不同,即连边权为1,否则为0,压缩路径时不断异或,可以通过0或1得到两点的关系。合并时解一个位运算的方程,可得一个根连向另一个根的权值,看code,就不细讲了。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 #include<queue> 7 #define dbg(x) cerr<<#x<<" = "<<x<<endl 8 #define ddbg(x,y) cerr<<#x<<" = "<<x<<" "<<#y<<" = "<<y<<endl 9 using namespace std; 10 typedef long long ll; 11 template<typename T>inline char MIN(T&A,T B){return A>B?A=B,1:0;} 12 template<typename T>inline char MAX(T&A,T B){return A<B?A=B,1:0;} 13 template<typename T>inline T _min(T A,T B){return A<B?A:B;} 14 template<typename T>inline T _max(T A,T B){return A>B?A:B;} 15 template<typename T>inline T read(T&x){ 16 x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1; 17 while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x; 18 } 19 const int N=10000+7; 20 struct kishin_sagume{ 21 int l,r,p; 22 }q[N]; 23 int a[N<<1],fa[N<<1],d[N<<1]; 24 int L,n,m,x,y,fx,fy,flag,i; 25 inline int Get(int x){ 26 if(fa[x]==x)return x; 27 int ret=Get(fa[x]);d[x]^=d[fa[x]]; 28 return fa[x]=ret; 29 } 30 31 int main(){//freopen("test.in","r",stdin);//freopen("test.out","w",stdout); 32 read(L),read(n);char s[8]; 33 for(i=1;i<=n;++i){ 34 read(q[i].l),read(q[i].r),a[++m]=--q[i].l,a[++m]=q[i].r; 35 scanf("%s",s);q[i].p=s[0]=='o'; 36 } 37 sort(a+1,a+m+1),m=unique(a+1,a+m+1)-a-1; 38 for(i=1;i<=m;++i)fa[i]=i; 39 for(i=1;i<=n;++i){ 40 x=lower_bound(a+1,a+m+1,q[i].l)-a,y=lower_bound(a+1,a+m+1,q[i].r)-a; 41 fx=Get(x),fy=Get(y); 42 if(fx^fy)fa[fx]=fy,d[fx]=q[i].p^d[x]^d[y]; 43 else if(d[x]^d[y]^q[i].p)break; 44 } 45 return printf("%d\n",i-1),0; 46 }
扩展域:同奇偶时连奇数域和偶数域分别连边,否则交错,边的含义是可以产生关系,或者说可以推出。已知他是满足传递性的。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 #include<queue> 7 #define dbg(x) cerr<<#x<<" = "<<x<<endl 8 #define ddbg(x,y) cerr<<#x<<" = "<<x<<" "<<#y<<" = "<<y<<endl 9 using namespace std; 10 typedef long long ll; 11 template<typename T>inline char MIN(T&A,T B){return A>B?A=B,1:0;} 12 template<typename T>inline char MAX(T&A,T B){return A<B?A=B,1:0;} 13 template<typename T>inline T _min(T A,T B){return A<B?A:B;} 14 template<typename T>inline T _max(T A,T B){return A>B?A:B;} 15 template<typename T>inline T read(T&x){ 16 x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1; 17 while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x; 18 } 19 const int N=10000+7; 20 struct matara_okina{ 21 int l,r,p; 22 }q[N]; 23 int a[N<<1],fa[N<<2]; 24 int L,n,m,x,y,i; 25 inline int Get(int x){ 26 return fa[x]^x?fa[x]=Get(fa[x]):x; 27 } 28 29 int main(){//freopen("test.in","r",stdin);//freopen("test.out","w",stdout); 30 read(L),read(n);char s[8]; 31 for(i=1;i<=n;++i){ 32 read(q[i].l),read(q[i].r),a[++m]=--q[i].l,a[++m]=q[i].r; 33 scanf("%s",s);q[i].p=s[0]=='o'; 34 } 35 sort(a+1,a+m+1),m=unique(a+1,a+m+1)-a-1; 36 for(i=1;i<=(m<<1);++i)fa[i]=i; 37 for(i=1;i<=n;++i){ 38 x=lower_bound(a+1,a+m+1,q[i].l)-a,y=lower_bound(a+1,a+m+1,q[i].r)-a; 39 if(q[i].p){ 40 if(Get(x)==Get(y))break; 41 fa[Get(x)]=Get(y+m),fa[Get(x+m)]=Get(y); 42 } 43 else{ 44 if(Get(x)==Get(y+m))break; 45 fa[Get(x)]=Get(y),fa[Get(x+m)]=Get(y+m); 46 } 47 } 48 return printf("%d\n",i-1),0; 49 }