POJ ~ 1733 ~ Parity game (带权并查集+map离散化)

题意:一个长度为N的01串,M句话,每次告诉你a~b区间内有奇数个或者偶数个1,问第一个与前面矛盾的位置在哪,输出他的上一个的位置,没有错误输出M。

思路:因为N为10^9,明显开不了那么大的数组,而M只有5000,也就是说中间会有很多数字没有。我们就想到了离散化,只保存有的数字,没有的数字不开辟空间。对于每个数字需要保存两个值,一个为父节点,一个为权值。用map<int, pair<int, int> >即可,第一个int表示下标,pair中第一个int表示父节点,第二个表示权值(0表示偶数,1表示奇数)。其他的都跟之前的那道食物链的题目基本一样了。

//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<string>
#include<cstdlib>
#include<map>
using namespace std;
int n, m, ans;
map<int, pair<int, int> > M;
void init()
{
    ans = -1;
    M.clear();
}
int Find(int x)
{
    if (M[x].first == x) return x;
    int t = M[x].first;
    M[x].first = Find(M[x].first);
    M[x].second = (M[x].second + M[t].second) % 2;
    return M[x].first;
}
int main()
{
    while(~scanf("%d%d", &n, &m))
    {
        init();
        for (int i = 0; i < m; i++)
        {
            int x, y, t;
            //string s;
            //cin >> x >> y >> s;
            char s[10];
            scanf("%d%d%s", &x, &y, s);
            x--;
            if (ans != -1) continue;//已经有错了,只需要把输入即可
            if (!M.count(x)) { M[x] = make_pair(x, 0); }
            if (!M.count(y)) { M[y] = make_pair(y, 0); }
            if (s[0] == 'e') t = 0;//偶数
            else if(s[0] == 'o') t = 1;//奇数
            int root1 = Find(x), root2 = Find(y);
            if (root1 != root2)//根节点不同,合并
            {
                M[root1].first = root2;
                M[root1].second = (M[y].second + t - M[x].second + 2) % 2;
            }
            else
            {
                if (abs(M[x].second - M[y].second) % 2 != t) ans = i;//根节点相同判断是否有错
            }
        }
        if(ans == -1) ans = m;//全对
        printf("%d\n", ans);
    }
    return 0;
}
/*
10
5
1 2 even
3 4 odd
5 6 even
1 6 even
7 10 odd
*/





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值