CDOJ1464 Parity Game [并查集]

这道题我用的并查集做的。
首先对数据做离散化。

按给出的顺序依次处理每次问答。
并查集每个节点维护三个值:
root:该点的根节点(从根节点到该节点的整个区间的奇偶性已经确定);
sign:该节点是否是某个奇偶性确定区间的右端点;
eo:该集合的根节点到该点的区间的奇偶性;

结束:在遇到某区间的奇偶性出现矛盾时结束(后来得到的奇偶性和之前确定的奇偶性不同)。

每次先找到a-1和b的根节点;
如果a-1没有根节点:

  如果b没有根节点:b的root设为a,更新b的sign,eo;
  如果b的根节点就是a,考察a到b区间是否出现矛盾;
  否则得到两个区间[fb,a-1]和[a,b],或[a,fb-1]和[fb,b],这两个区间的奇偶性都可得到,
  更新其奇偶性。

如果a-1的根节点为fa:

  如果b没有根节点,b的根基点设为a,更新b的sign和eo;
  如果fa==fb,做奇偶性判断;
  否则,会从区间的并分解得到两个或三个互不相交的区间,这些区间的奇偶性可以得到。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<string>
#include<cmath>
#include<iostream>
#include<algorithm>

using namespace std;

#define PN printf("\n");

char chrn;
#define SCRN while(scanf("%c",&chrn) && chrn!='\n');

typedef struct
{
    int a,b,id,eo;
}node1;

typedef struct
{
    int n,id,type;
}node2;

typedef struct
{
    int root,sign,eo;
}node3;

int n,last;
node1 a[5001];
node2 b[10001];
node3 set[10001];

bool cmp(node2 a,node2 b)
{
    if(a.n<b.n)
        return true;
    return false;
}

void discrete(int t)
{
    int i,num,m;
    sort(b,b+t,cmp);
    num=0;
    m=b[0].n;
    for(i=0; i<t; i++)
    {
        if(b[i].n>m)
        {
            m=b[i].n;
            num++;
        }
        if(b[i].type==1)
            a[b[i].id].a=num;
        else
            a[b[i].id].b=num;
    }
}

void ini_set()
{
    int i;
    for(i=0; i<=10000; i++)
        set[i].sign = 0;
}

int findroot(int k)
{
    int root;
    if(k<0 || set[k].sign == 0)
        return -1;
    root = findroot(set[k].root-1);
    if(root == -1)
        return set[k].root;
    else
    {
        set[k].eo ^= set[set[k].root-1].eo;
        return set[k].root = root;
    }
}

void D()
{
    int i,fa,fb,eo;
    node1 nd;
    last=0;
    ini_set();
    for(i=0; i<n; i++)
    {
        last++;
        nd = a[i];
        fa = findroot(nd.a-1);
        fb = findroot(nd.b);
        if(fa == -1)
        {
            if(fb == -1)
            {
                set[nd.b].sign = 1;
                set[nd.b].root = nd.a;
                set[nd.b].eo = nd.eo;
            }
            else if(fb == nd.a)
            {
                if(set[nd.b].eo != nd.eo){
                    //printf("OP2:");
                    return;
                }
            }
            else if(fb < nd.a)
            {
                set[nd.a-1].sign = 1;
                set[nd.a-1].root = fb;
                set[nd.a-1].eo = set[nd.b].eo ^ nd.eo;
            }
            else if(fb > nd.a)
            {
                set[fb-1].sign = 1;
                set[fb-1].root = nd.a;
                set[fb-1].eo = set[nd.b].eo ^ nd.eo;
                set[nd.b].root = nd.a;
                set[nd.b].eo = nd.eo;
            }
        }
        else
        {
            if(fb == -1)
            {
                set[nd.b].sign = 1;
                set[nd.b].root = fa;
                set[nd.b].eo = set[nd.a-1].eo ^ nd.eo;
            }
            else if(fa == fb)
            {
                if((set[nd.b].eo ^ set[nd.a-1].eo) !=nd.eo)
                {
                    //printf("OP1:");
                    return;
                }
            }
            else if(fb<fa)
            {
                set[fa-1].sign = 1;
                set[fa-1].root = fb;
                set[fa-1].eo = set[nd.a-1].eo ^ set[nd.b].eo ^ nd.eo;
            }
            else if(fb>fa && fb<nd.a)
            {
                set[fb-1].sign = 1;
                set[fb-1].root = fa;
                set[fb-1].eo = set[nd.a-1].eo ^ set[nd.b].eo ^ nd.eo;
            }
            else if(fb>nd.a)
            {
                set[fb-1].sign = 1;
                set[fb-1].root = nd.a;
                set[fb-1].eo = set[nd.b].eo ^ nd.eo;
                findroot(nd.b);
            }
        }
    }
    last++;
}

int main()
{
    int m,i,j;
    char s[5];
    while(scanf("%d",&m)!=EOF)
    {
        scanf("%d",&n);
        for(i=0,j=0; i<n; i++)
        {
            scanf("%d %d %s",&a[i].a,&a[i].b,s);
            if(s[0]=='e')
                a[i].eo=0;
            else
                a[i].eo=1;
            a[i].id=i+1;
            b[j].n=a[i].a;
            b[j].type=1;
            b[j++].id=i;

            b[j].n=a[i].b;
            b[j].type=2;
            b[j++].id=i;
        }
        discrete(2*n);
        D();
        printf("%d\n",last-1);
    }
    return 0;
}

posted on 2012-05-12 01:50  Lattexiaoyu  阅读(229)  评论(0编辑  收藏  举报

导航