poj 1733 - Parity game(离散化+并查集)

来源:互联网 发布:爆破手机号软件 编辑:程序博客网 时间:2024/05/13 22:58

有点难度的并查集题目。。。

题意:

    每次询问都能返回该区间内的1个数的奇偶性,问这些询问从第几个开始就不正确了。

思路:(from:http://www.cnblogs.com/ltang/archive/2010/12/07/1898919.html)

    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奇数

代码如下:

const int M = 10005;int hash[M], p[M], s[M];int nextString(){    char tmp[10];    scanf("%s", tmp);    if(strcmp(tmp,"even")==0) return 0;    return 1;}int hashf(int x){    int cur = x%M;    while(hash[cur]!=-1)        if(hash[cur]==x) return cur;        else cur = (cur+1)%M;    hash[cur] = x;    return cur;}int find(int x){    int tmp = p[x];    p[x] = (p[x]==x?x:find(p[x]));    s[x] = s[tmp]^s[x];    return p[x];}int main(){    int n, m, a, b, o, flag = 0, ans;    scanf("%d%d", &n, &m);    memset(hash,-1,sizeof(hash));    for(int i = 0; i < M; ++i) p[i] = i;    for(int i = 0; i < m; ++i)    {        scanf("%d%d", &a, &b);        o = nextString();        if(flag) continue;        int pa = hashf(a-1);        int pb = hashf(b);        int x = find(pa);        int y = find(pb);        if(x==y && s[pa]^s[pb]^o) flag = 1, ans = i;        else if(x!=y)        {            if(hash[x]>hash[y]) p[x] = y, s[x] = s[pa]^s[pb]^o;            else p[y] = x, s[y] = s[pa]^s[pb]^o;        }    }    flag?printf("%d\n", ans):printf("%d\n", m);    return 0;}


原创粉丝点击