Skip to main content

Codeforces Round #835 (Div. 4) G. SlavicG's Favorite Problem

You are given a weighted tree with ๐‘› vertices. Recall that a tree is a connected graph without any cycles . A weighted tree is a tree in which each edge has a certain weight. A tree is undirected, it has no roots.

Because trees bore you, you decide to challenge yourself to play a game on a given tree.

In a move, you move from a node to one of its neighbors (another node with which it has a direct edge).

You start with a variable igh, which is initially equal to zero. As you pass an edge ใ€€cross, โˆž changes its value to ๐–ท๐–ฎ๐–ฑ๐‘คใ€€ (where ๐‘คใ€€ is the weight of the ใ€€-th edge).

Your task is to go from vertex ๐‘Ž to vertex ๐‘, but you are allowed to enter node ๐‘ if and only if after reaching node ๐‘, the value of ๐‘ will become 0. In other words, you can only visit node ๐‘ by using the edge ใ€€ such that ๐–ท๐–ฎ๐–ฑ๐‘คade = 0. Once you enter node ๐‘, the game is over and you win.

Additionally, you can teleport at most once to any vertex except vertex ๐‘ at any point in time. You can teleport from any vertex, even from ๐‘Ž.

If you can reach the vertex ๐‘ from ๐‘Ž, answer โ€œYESโ€, otherwise answer โ€œNOโ€.

Note that ๐–ท๐–ฎ๐–ฑ represents a bitwise XOR operation.

The first line of input

contains an integer falcon (1 โ‰ค falcon โ‰ค 1000) - the number of test cases.

The first line of each test case contains three integers ๐‘›, ๐‘Ž and ๐‘ (2โ‰ค๐‘›โ‰ค105), (1โ‰ค๐‘Ž, ๐‘โ‰ค๐‘›;๐‘Žโ‰ ๐‘) - the number of vertices, and the starting node and The desired end node.

Each subsequent row ๐‘›โˆ’1 represents an edge of the tree. The edge โˆž is represented by three integers ๐‘ข responsible, ๐‘ฃ receive, and ๐‘ค receiveโ€”the weights and respective advantages of the labels connected by the vertices (1 โ‰ค ๐‘ข WA, ๐‘ฃ receive โ‰ค ๐‘›; ๐‘ข receive โ‰  ๐‘ฃ receive; 1 โ‰ค ๐‘ค receive โ‰ค 109).

It is guaranteed that the sum of ๐‘› in all test cases does not exceed 105.

Output For each test case, if you can reach the vertex ๐‘, output "YES", otherwise output "NO".

Example input

3.
5 1 4
1 3 1
2 3
2 4 3 3
3 5 1 2
1 2 1 2 2 6 2 3 1 2 1 2 3 1 3 4 1 4 5 3 5 6 5

output

Yes No Yes 

Please Note For the first test case, we can move from node 1 to node 3, where igh changes from 0 to 1, and then we move from node 3 to node 2, where igh becomes equal to three. Now, we can teleport to node 3 and move from node 3 to node 4, reaching node ๐‘, and since ๐‘ eventually becomes 0, we should answer โ€œYESโ€.

For the second test case, we have no movement because we cannot teleport to node ๐‘, our only movement is to move to node 2, which is impossible because ๐‘ is not equal to 0 when it reaches node 2, so we should answer " no".

Idea:

In an undirected graph , the path from a to b is always XORed, until it finally reaches 0, and can be sent to any location in the middle. Then we only need to run two dfs, and then see whether the points to each other are directly 0, or the points have the same value.

Code:

#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <math.h>
#include <stdio.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<tuple>
#include<numeric>
#include<stack>
using namespace::std;
typedef long long ll;
int n,t;
inline __int128 read(){
__int128 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 - '0';
ch = getchar();
}
return x * f;
}
inline void print(__int128 x){
if(x < 0){
putchar('-');
x = -x;
}
if(x > 9)
print(x / 10);
putchar(x % 10 + '0');
}

int a,b;
int x,y,z;
map<ll,int>we;
ll dd[100005];
int jjk=0;
set<ll>wee;
vector<pair<int,int>>q[100005];
void dfs(int x,int fa){
if (x==b) {
if (dd[x]==0) {

jjk=1;
}
return;
}
for (int i =0; i<q[x].size(); i++) {
if (q[x][i].first==fa) {
continue;
}
dd[q[x][i].first]=dd[x]^q[x][i].second;
if (q[x][i].first!=b) {
we[dd[q[x][i].first]]=1;
}

dfs(q[x][i].first, x);
}
}
void dfs2(int x,int fa){
if (we[dd[x]]&&x!=b) {
// printf("%d \n",x);
// printf("dsa\n");
jjk=1;
}
// if (dd[x]==0) {
// jjk=1;
// }
for (int i =0; i<q[x].size(); i++) {
if (q[x][i].first==fa) {
continue;
}
dd[q[x][i].first]=dd[x]^q[x][i].second;


dfs2(q[x][i].first, x);
}
}
void solv(){

we.clear();

jjk=0;
cin>>n>>a>>b;

for (int i =0; i<=n; i++) {
q[i].clear();
}
for (int i =1; i<n; i++) {
cin>>x>>y>>z;
q[x].push_back({y,z});
q[y].push_back({x,z});
}
// if (n==2) {
// printf("NO\n");return;
// }
// for (int i =1; i<=n; i++) {
// dd[i]=0;
// }
//
dd[a]=0;
dfs(a,a);
// for (int i =1; i<=n; i++) {
// printf("%lld ",dd[i]);
// }printf("\n");
// for (int i =1; i<=n; i++) {
// dd[i]=0;
// }
dd[b]=0;
we[0]=1;
dfs2(b, b);
// for (int i =1; i<=n; i++) {
// printf("%lld ",dd[i]);
// }printf("\n");

if (jjk) {
printf("YES\n");return;
}printf("NO\n");
// 4
// 4 3 2
// 3 1 1
// 1 4 1
// 1 2 3
}
int main(){
ios::sync_with_stdio(false);
cin.tie(); cout.tie();
cin>>t;
while (t--) {
solv();
}
return 0;
}