题意:每次给定一个条件i,j,k,表示[i,j]内的异或和为k。判断该条件是否与之前的条件冲突,冲突则输出,不冲突则保存下来。若无冲突条件则输出-1。
思路:设一个数组f[i]表示[1,i]的异或和,那么[i,j]的异或和则=f[i-1]^f[j]。根据题目给的条件,用带权并查集,father[i].v表示i的父亲,father[i].w表示i与其父亲的异或和。每次通过询问并查集来判断是否冲突,以及合并来实现条件的保存。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define PI acos(-1)
#define INF 0x3f3f3f3f
#define NUM 101000
#define debug false
#define ll long long
#define lowbit(x) ((-(x))&(x))
#define ffor(i,d,u) for(int i=(d);i<=(u);++i)
#define _ffor(i,u,d) for(int i=(u);i>=(d);--i)
#define mst(array,Num) memset(array,Num,sizeof(array))
const int p = 1e9+7;
struct s
{
int v;
int w;
}father[NUM];
int n,m;
bool flag;
template <typename T>
void read(T& x)
{
x=0;
char c;
while((c=getchar())<'0'||c>'9');
do((x*=10)+=((int)(c-'0')));while((c=getchar())>='0'&&c<='9');
}
template <typename T>
void write(T x)
{
int len=0;char c[21];
if(x<0)putchar('-');
x=abs(x);
do{++len;c[len]=(char)((x%10)+'0');}while(x/=10);
_ffor(i,len,1)putchar(c[i]);
}
int getfather(int x)
{
if(father[x].v==x)
return x;
int y=father[x].v;
father[x].v=getfather(father[x].v);
father[x].w^=father[y].w;
return father[x].v;
}
void solve(int i,int l,int r,int w)
{
int fl=getfather(l);
int fr=getfather(r);
if(fl==fr)
{
if((father[l].w^father[r].w)!=w)
{
write(i);
putchar('\n');
flag=true;
}
return ;
}
father[fr].v=fl;
father[fr].w=father[l].w^father[r].w^w;
}
void AC()
{
int x,y,w;
while(scanf("%d",&n)!=EOF)
{
read(m);
flag=false;
ffor(i,1,n)
{
father[i].v=i;
father[i].w=0;
}
ffor(i,1,m)
{
read(x),read(y),read(w);
solve(i,x-1,y,w);
}
if(!flag)
{
write(-1);
putchar('\n');
}
}
}
int main()
{
AC();
return 0;
}