题目链接:https://codeforces.ml/contest/1760/problem/G

div4最接近ak的一场,这个题没有读明白。其实上一个题也应该要整理的,做法还是有些复杂。这个题我的写法和别人写的相比也复杂一些。尤其是在树的遍历操作上,开sign是容易出错的==

题意:大意是给出一个n个节点的树,你需要从a走到b。到b时,你需要异或b的值等于0,才能进入b。每个边权都有一个值,初始值为0 。

在途中,你可以选择在任意位置,使用一次转移到其他任意位置(只能一次)。求是否可以到达b?

解决方法:跑一遍正向dfs,获得所有边权后的异或值,然后反向跑一遍dfs,如果这个异或值曾经获得过那么就可以从曾经的位置转移过来,然后正向异或还一遍正好为0.

涉及的数学规律,异或运算

0 5 6 3 2互相异或  =  0 2 3 6 5 互相异或
结论,一个点异或到另一个点 等于 从另一个点异或到这个点

a^b = b^a   a^b^c = c^b^a 等等

通过百度进一步研究,异或存在一定的结合律,在数一定的情况想先异或哪个数和后异或哪个数结果一样,可以参加加分结合律
同样的异或存在一定的规律,https://blog.csdn.net/a3630623/article/details/12371727

从1异或到n只需要一个O(1)的复杂度,同一样从a异或到b也只需要常数级别复杂度

本题code:

#include<bits/stdc++.h>
using namespace std;
#pragma GCC optimize(2)
#define ll long long
#define endl '\n'
#define cyes cout<<"YES\n"
#define cno cout<<"NO\n"
#define mem(a) memset((a),0,sizeof (a))
const int mod7 = 1e9+7;
const int mod9 = 998244353;

inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
	return x*f;
}
struct tdata{
	int v;
	int w;
};
const int nn = 1e5+10;
vector<tdata> ve[nn];
bool sign[nn];
bool ok = false;
map<int,bool> mp;
int n,a,b;
void dfs1(int cur,int num){
	for(int i=0;i<ve[cur].size();i++){
		tdata nxt = ve[cur][i];
		if(!sign[nxt.v]&&nxt.v!=b){
			mp[num^nxt.w]=true;
			sign[nxt.v] = true;
			dfs1(nxt.v,num^nxt.w);
		}
	}
}
void dfs2(int cur,int num){
	if(ok) return;
	for(int i=0;i<ve[cur].size();i++){
		tdata nxt = ve[cur][i];
		if(!sign[nxt.v]){
			if(mp[num^nxt.w]){
				ok = true;
				return;
			}
			sign[nxt.v] = true;
			dfs2(nxt.v,num^nxt.w);
		}
		
	}
}
void solve()
{
	cin>>n>>a>>b;
	mp.clear();ok = false;
	for(int i=1;i<=n;i++)
		ve[i].clear();	
	int x,y,z;
	for(int i=1;i<n;i++){
		cin>>x>>y>>z;
		ve[x].push_back({y,z});
		ve[y].push_back({x,z});
	}
	mp[0] = true;
	
	mem(sign);
	sign[a] = true;
	dfs1(a,0);
	mem(sign);
	sign[b] = true;
	dfs2(b,0);
	
	if(ok) cyes;
	else cno; 
}
int main()
{
 	//cin.ignore(numeric_limits<streamsize>::max(),'\n')
	ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	int t;
	cin>>t;
	while(t--)
	{
		solve();
	}
}