并查集-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);
}
posted @ 2017-02-28 22:21  largecube233  阅读(115)  评论(0编辑  收藏  举报