Ural 1003. Parity

给出在一个区间内1的奇偶性,输出在第一次出现矛盾位置。

个人感觉是一个比较难也比较好的并查集的题目,一开始并没有看出来,囧。

把给出的区间转化为前开后闭区间,查询区间的短点是否为同一个祖先,若是,则判断奇偶性是否正确。

若不在同一个区间把区间短点合并。

注意两点:

1.记录当前区间短点到最远祖先这段区间的奇偶性。

2.合并的时候,是把要合并的区间端点的两个祖先合并。路径压缩的时候修改祖先,要修改记录的奇偶性。

具体修改方法在代码。

#include <iostream>
#include <cstdio>
#include <map>
using namespace std;
const int maxn=10005;
const int MOD=9941;

int par[maxn],num[maxn],c[maxn];
map<int,int>Index;
int find(int s)
{
   if(s!=par[s])
   {
       int p=par[s];
       par[s]=find(par[s]);
       c[s]=c[p]^c[s];
   }
   return par[s];
}
void merge(int fa,int fb,int a,int b,int o)
{
    if(num[fa]<num[fb])
    {
        par[fb]=fa;
        c[fb]=c[a]^c[b]^o;
    }
    else
    {
        par[fa]=fb;
        c[fa]=c[a]^c[b]^o;
    }
}
int main()
{
    //freopen("data","r",stdin);
    int len,n,tag;
    int x,y,ix,iy,fx,fy;
    char str[10];
    while(scanf("%d",&len)&&len!=-1)
    {
        for(int i=0;i<maxn;i++)
        {
            par[i]=i;
            c[i]=0;
        }
        int dex=0,i;
        scanf("%d",&n);
        tag=n;
        Index.clear();
        for(i=0;i<n;i++)
        {
            scanf("%d%d%s",&x,&y,str);
            if(Index.find(x-1)==Index.end())
            {
                Index[x-1]=dex++;
                num[dex]=x;
            }
            ix=Index[x-1];
            if(Index.find(y)==Index.end())
            {
                Index[y]=dex++;
                num[dex]=y;
            }
            iy=Index[y];
            fx=find(ix),fy=find(iy);
            int judge=str[0]=='o'?1:0;
            if(fx==fy&&(c[ix]^c[iy]^judge))
            {
                tag=i;
                break;
            }
            else if(fx!=fy)
            {
                merge(fx,fy,ix,iy,judge);
            }
        }
        for(int j=i+1;j<n;j++)
        scanf("%d%d%s",&x,&y,str);
        printf("%d\n",tag);
    }

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值