【并查集】POJ 1733 Parity game

POJ 1733 : Parity game

题意

对于一串很长的只含有0,1的字符串,给出信息x,y ,op(op可以是even,odd),说明序号从x到y之间有even(偶数)或者odd(奇数)个1。求最早出现信息错误的行数。

分析

若x, y之间1的个数为【偶】数个, 那么[1,x) 与[1,y]中1的个数【同】奇偶性。
若x, y之间1的个数为【奇】数个, 那么[1,x) 与[1,y]中1的个数【异】奇偶性。
我们可以将其理解为若输入x, y, even, 即x, y属于同种, 反之则属于不同种。
由于题目给出的区间是闭区间[x,y],我们需要处理成[x,y+1),也可以处理成(x, y].

由于题目数据比较大,我们需要进行离散化处理,这里使用的是STL的map容器。

代码

#include <iostream>
#include <cstdio>
#include <map>
#include <string.h>
using namespace std;

const int MAXNUM = 20000 + 10;
int id[MAXNUM];
int Size[MAXNUM];
int r[MAXNUM];
// 初始化
void make_set(int n){
    for(int i = 1 ; i <= n ; i++){
        id[i] = i;
        Size[i] = 1;
        r[i] = 0;
    }
}

// 查找父节点
int Find(int p) {
    while (id[p] != id[id[p]]) {   //如果q不是其所在子树的根节点的直接孩子
        r[p] = (r[p] + r[id[p]] ) % 2;
         id[p] = id[id[p]];          //对其父节点到其爷爷节点之间的路径进行压缩
      }
    return id[p];
}

// 合并 p ,q节点
void Union(int p, int q, int d) {
    int pRoot = Find(p);
    int qRoot = Find(q);

    if (pRoot == qRoot) {
        return;
    }
    id[qRoot] = pRoot;
    r[qRoot] = (r[p] - r[q] + 2 + d) % 2;
}

int main(){
    //freopen("input.txt","r",stdin);
    //freopen("output.txt","w",stdout);
    int n , m;
    int p , q;
    int d;
    char c[10];
    map<int , int> mp;
    int cnt = 1;
    int ans = 0;
    scanf("%d %d", &n , &m);
    make_set(m * 2 + 10);
    for(int i = 1 ; i <= m ; i++){
        scanf("%d %d %s", &p, &q ,&c);

        q++;
        int flag = 0;
        if(strstr(c,"even"))
            d = 0;
        else
            d = 1;

        // 离散化
        if(!mp[p])
            mp[p] = cnt++;
        if(!mp[q])
            mp[q] = cnt++;

        if(Find(mp[p]) == Find(mp[q])){
            // 不是同类
            if(d == 0 && r[mp[p]] != r[mp[q]])
                flag = 1;
            // 如果 x 没有吃 y
            if(d == 1 && (r[mp[p]] + 1) % 2 != r[mp[q]])
                flag = 1;
        }else{
            Union(mp[p], mp[q], d);
        }


        if(ans == 0 && flag == 1)
            ans = i;
    }
    if(ans == 0)
        ans = m + 1;
    printf("%d\n",ans - 1);

    return 0;
}

猜你喜欢

转载自blog.csdn.net/u013075699/article/details/80348658