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

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

题意:

    每次询问都能返回该区间内的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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值