原题链接:https://codeforces.com/contest/1760/problem/G
题意:给定一棵树,给定起点和终点,要求从起点s到终点t的路径上的权值异或为0;其中有且仅有一次,可以从一点跳到除终点t外任意一点。问能否做到,能输出“YES”,否则输出“NO”;
题解:从起点s向任意方向走,将到除了终点t的所有路径的异或存入;再从起点t向任意方向走,记录路径的异或,倘若在上一次dfs中已经将此异或值存入,则表示可以经过跳跃使异或为0。
#pragma GCC optimize(2)
#include <iostream>
#include <vector>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <bitset>
#include <unordered_map>
#include <set>
#define quick_cin() cin.tie(0),cout.tie(0),ios::sync_with_stdio(false)
#define endl "\n"
using namespace std;
const int N = 100010, mod = 1000000007;
typedef long long LL;
typedef pair<int, int> PII;
int T;
int n, m;
int s, t;
set<int> S;
int f = 1;
int h[N], e[N * 2], ne[N * 2], w[N * 2], idx;
void add(int a, int b, int c)
{
e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;
}
void dfs_S(int u, int fa, int sum)
{
if (u == t) return;
S.insert(sum);
for (int i = h[u]; ~i; i = ne[i])
{
int j = e[i];
if (j == fa) continue;
dfs_S(j, u, sum ^ w[i]);
}
}
void dfs_T(int u, int fa, int sum)
{
if (!f) return;//倘若已经找到就不需要继续便利了,枝剪
if (S.count(sum) != 0 && u != t)//此sum之前存在,且跳跃到的点不是终点
{
f = 0;
return;
}
for (int i = h[u]; ~i; i = ne[i])
{
int j = e[i];
if (j == fa) continue;
dfs_T(j, u, sum ^ w[i]);
}
}
void solve()
{
f = 1;
S.clear();
memset(h, -1, sizeof h);
idx = 0;
cin >> n >> s >> t;
for (int i = 1; i < n; i ++ )
{
int a, b, c;
cin >> a >> b >> c;
add(a, b, c), add(b, a, c);
}
dfs_S(s, -1, 0);
dfs_T(t, -1, 0);
if (!f) cout << "YES" << endl;
else cout << "NO" << endl;
}
signed main()
{
quick_cin();
cin >> T;
// T = 1;
while (T -- )
{
solve();
}
}