给出在一个区间内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;
}