这是一道关于并查集的题目,和HDU-1829很相似,不过数据范围有了一点改变,HDU-1829在此:https://vjudge.net/problem/16380/origin
理论上这一题和HDU-1829应该都有两种方法,一个是设置两个并查集,将冲突的两个精灵合并入两个不同的并查集中,在合并的过程中如果发现合并冲突则表明出现问题,直接记录位置输出即可,但我用这个做法一直TLE,加了判断条件优化也过不了,不知道是不是数据范围过大的原因.(还是我写得太丑了)。
第二种方法则是同时记录偏移量和合并元素,倘若出现新输入的两个元素位于同一集合且偏移量相同,表明该两个元素与同一个元素都有交集,加上他们自身也有交集,表明他们同性,存在错误记录。
#include<iostream>
#include<cstdio>
using namespace std;
const int maxn=50005;
int fa1[maxn],rel[maxn];
int find1(int x)
{
if(fa1[x]==x)
return fa1[x];
int tem=fa1[x];
fa1[x]=find1(fa1[x]);
rel[x]=(rel[x]+rel[tem])%2;
return fa1[x];
}
void merge1(int x,int y)
{
int fx=find1(x),fy=find1(y);
fa1[fx]=fy;
rel[fx]=(rel[y]-rel[x]+1)%2;
}
int main()
{
int T,cnt=0;
scanf("%d",&T);
while(T--)
{
int n,m,flag1=-1,flag2=0;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
fa1[i]=i;
rel[i]=0;
}
for(int i=0;i<m;i++)
{
int a,b;
scanf("%d%d",&a,&b);
if(flag2==1)
continue;
if(find1(a)==find1(b))
{
if(rel[a]==rel[b]&&flag2==0)
{
flag2++;
flag1=i+1;
}
}
else
merge1(a,b);
}
printf("%d\n",flag1);
}
return 0;
}
/**********************************************************************
Problem: 1904
User: 3901160220
Language: C++
Result: AC
Time:144 ms
Memory:2088 kb
**********************************************************************/