题目链接:https://nanti.jisuanke.com/t/28968
题目大意: n个数字c个条件,然后n-1条边,问从上到下最多满足几个条件
题目思路:树上的异或,两点间无论怎么走都是两者最短路径上的异或和。r[i]表示i点到根节点的路径异或和。所以每次查条件的时候,如果两个人在同一链,那他俩有同一根节点,那么两者到根节点异或和的异或就是两者最近路上的异或。如果不是同一条链,那么就让二者合并。路径压缩的时候就把一条链上,同时更新r[i]
以下是代码:
#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define MAXN 100005
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define ll long long
int pre[MAXN];
ll r[MAXN];
int Find(int x){
if(x==pre[x])return x;
int root=Find(pre[x]);
r[x]^=r[pre[x]];
return pre[x]=root;
}
int main()
{
int t,n,c,x,y;ll z;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&c);
rep(i,1,n){
pre[i]=i;
r[i]=0;
if(i==n)break;
scanf("%d%d",&x,&y);
}
int ans=n+1;
rep(i,1,c){
scanf("%d%d%d",&x,&y,&z);
if(ans!=n+1)continue;
int xx=Find(x),yy=Find(y);
if(xx==yy&&(r[x]^r[y])!=z)ans=i;
else{
pre[xx]=yy;
r[xx]=r[x]^r[y]^z;
}
}
printf("%d\n",ans-1);
}
return 0;
}