Check if XOR of each connected component becomes equal after removing atmost P edges
Last Updated :
09 Dec, 2022
Given, a Tree with N nodes, and an integer P, the task is to remove at edges in range [1, P) and find the XOR of nodes for every connected component formed. If node’s values come out to be equal for all connected components formed, Print “YES” else “NO”.
Examples:
Input: N = 5, P = 5, Edges[][]={ { 1, 2 }, { 2, 3 }, { 1, 4 }, { 4, 5 }}, nodes[] = {2, 2, 2, 2, 2}
Output: YES
Explanation: We can remove all edges, then there will be 5 connected components each having one node with value 2, thus XOR of each of them will be 2.
Input: N = 5, P = 2, Edges[][]={ { 1, 2 }, { 2, 3 }, { 1, 4 }, { 4, 5 }}, nodes[] = {1, 6, 4, 1, 2}
Output: YES
Explanation: As, p = 2, atleast one edge need to be removed so, removing edge (4, 5), gives two connected components.
XOR of first component would be, arr1 XOR arr2 XOR arr3 XOR arr4= 1 XOR 6 XOR 4 XOR 1 => 2.
XOR of second component will be arr5 = 2. (Thus, both equal).
Approach: The approach to solve this problem is based on following observations:
The fact here, is that deletion of edges should be either once or twice, as:
- Removing one edge gives us 2 connected components, which should have same XOR and thus by properties of xor if XOR1 == XOR2, then XOR1 ^ XOR2 = 0, where ^ is the bitwise XOR.
- Similarly, if XOR of the whole tree is 0, removing any edge, will give 2 connected components where both components would have equal value, thus answer = “YES”.
- Now, if we delete 2 edges, deleting more than that would just merge the other components with each other. For ex: if there are 4 or more connected components, we can reduce and merge them, as for 4 it can be reduced to 2 components (which will fall in the case if we remove 1 edge).
- Now, deleting 2 edges gives us a minimum of 3 connected components, using properties of xor we know, that XOR1 ^ XOR2 ^ XOR3 = let’s say some value(y), which means we need to find such subtrees(or say search for 2 edges to remove) whose XOR is equal to some value(y), and if we find it then answer = “YES” else “NO”, such that p>2.
- For ex: say, if we have total XOR = some value(y), with N = 4, there can be 3 segments whose XOR would have been y, then the total elements could get XOR = y, such that p > 2.
So, overall it can be said that if we find two subtrees whose XOR = y, and if our total XOR was y, we can say that our left out component/segment XOR would also be y, thus answer = “YES”, such that p > 2, using above property XOR1 ^ XOR2 ^ XOR3 = some value(y),
Follow the steps below to apply the above approach:
To find such subtrees, with a minimum of 3 connected components, it can be done easily using DFS traversal and during backtracking, we will store each index XOR at each iteration.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5;
vector< int > adj[N];
int nodes[N], cal_XOR[N];
vector< bool > visited(N);
int counter = 0;
int dfs_First( int x)
{
cal_XOR[x] = nodes[x];
visited[x] = true ;
for ( auto y : adj[x]) {
if (!visited[y]) {
cal_XOR[x] ^= dfs_First(y);
}
}
return cal_XOR[x];
}
int dfs_Second( int x)
{
visited[x] = true ;
int temp = nodes[x];
for ( auto y : adj[x]) {
if (!visited[y]) {
temp ^= dfs_Second(y);
}
}
if (temp == cal_XOR[0]) {
temp = 0;
counter++;
}
return temp;
}
void addEdge( int u, int v)
{
adj[u].push_back(v);
adj[v].push_back(u);
}
void init( int edges[4][2], int numEdges)
{
for ( int i = 0; i < numEdges; i++) {
edges[i][0]--;
edges[i][1]--;
addEdge(edges[i][0], edges[i][1]);
}
}
int main()
{
int n = 5, p = 2;
nodes[0] = 1, nodes[1] = 6, nodes[2] = 4,
nodes[3] = 1, nodes[4] = 2;
for ( int i = 0; i < n; i++) {
visited[i] = false ;
}
int edges[4][2]
= { { 1, 2 }, { 2, 3 }, { 1, 4 }, { 4, 5 } };
init(edges, 4);
dfs_First(0);
for ( int i = 0; i < n; i++) {
visited[i] = false ;
}
bool answer = false ;
if (cal_XOR[0] == 0) {
answer = true ;
}
else {
dfs_Second(0);
if (counter >= 2 and p != 2) {
answer = true ;
}
}
if (answer == true ) {
cout << "YES"
<< "\n" ;
}
else {
cout << "NO"
<< "\n" ;
}
counter = 0;
for ( int i = 0; i < n; i++) {
adj[i].clear();
cal_XOR[i] = nodes[i] = 0;
}
}
|
Java
import java.util.*;
public class GFG {
static int N = 100000 ;
static ArrayList<ArrayList<Integer> > adj
= new ArrayList<>();
static int [] nodes = new int [N];
static int [] cal_XOR = new int [N];
static boolean [] visited = new boolean [N];
static int counter = 0 ;
static int dfs_First( int x)
{
cal_XOR[x] = nodes[x];
visited[x] = true ;
for (Integer y : adj.get(x))
{
if (!visited[y])
{
cal_XOR[x] ^= dfs_First(y);
}
}
return cal_XOR[x];
}
static int dfs_Second( int x)
{
visited[x] = true ;
int temp = nodes[x];
for (Integer y : adj.get(x)) {
if (!visited[y]) {
temp ^= dfs_Second(y);
}
}
if (temp == cal_XOR[ 0 ])
{
temp = 0 ;
counter++;
}
return temp;
}
static void addEdge( int u, int v)
{
adj.get(u).add(v);
adj.get(v).add(u);
}
static void init( int [][] edges, int numEdges)
{
for ( int i = 0 ; i < numEdges; i++) {
edges[i][ 0 ]--;
edges[i][ 1 ]--;
addEdge(edges[i][ 0 ], edges[i][ 1 ]);
}
}
public static void main(String[] args)
{
int n = 5 , p = 2 ;
nodes[ 0 ] = 1 ;
nodes[ 1 ] = 6 ;
nodes[ 2 ] = 4 ;
nodes[ 3 ] = 1 ;
nodes[ 4 ] = 2 ;
for ( int i = 0 ; i < n; i++) {
adj.add( new ArrayList<>());
}
int [][] edges
= { { 1 , 2 }, { 2 , 3 }, { 1 , 4 }, { 4 , 5 } };
init(edges, 4 );
dfs_First( 0 );
for ( int i = 0 ; i < n; i++) {
visited[i] = false ;
}
boolean answer = false ;
if (cal_XOR[ 0 ] == 0 ) {
answer = true ;
}
else {
dfs_Second( 0 );
if (counter >= 2 && p != 2 ) {
answer = true ;
}
}
if (answer == true ) {
System.out.println( "YES" );
}
else {
System.out.println( "NO" );
}
counter = 0 ;
for ( int i = 0 ; i < n; i++) {
adj.get(i).clear();
cal_XOR[i] = nodes[i] = 0 ;
}
}
}
|
Python3
N = int ( 1e5 )
adj = [[] for _ in range (N)]
nodes, cal_XOR = [ 0 for _ in range (N)], [ 0 for _ in range (N)]
visited = [ 0 for _ in range (N)]
counter = 0
def dfs_First(x):
global N, adj, nodes, cal_XOR, visited, counter
cal_XOR[x] = nodes[x]
visited[x] = True
for y in adj[x]:
if ( not visited[y]):
cal_XOR[x] ^ = dfs_First(y)
return cal_XOR[x]
def dfs_Second(x):
global N, adj, nodes, cal_XOR, visited, counter
visited[x] = True
temp = nodes[x]
for y in adj[x]:
if ( not visited[y]):
temp ^ = dfs_Second(y)
if (temp = = cal_XOR[ 0 ]):
temp = 0
counter + = 1
return temp
def addEdge(u, v):
global N, adj, nodes, cal_XOR, visited, counter
adj[u].append(v)
adj[v].append(u)
def init(edges, numEdges):
global N, adj, nodes, cal_XOR, visited, counter
for i in range ( 0 , numEdges):
edges[i][ 0 ] - = 1
edges[i][ 1 ] - = 1
addEdge(edges[i][ 0 ], edges[i][ 1 ])
if __name__ = = "__main__" :
n, p = 5 , 2
nodes[ 0 ], nodes[ 1 ], nodes[ 2 ] = 1 , 6 , 4
nodes[ 3 ], nodes[ 4 ] = 1 , 2
for i in range ( 0 , n):
visited[i] = False
edges = [[ 1 , 2 ], [ 2 , 3 ], [ 1 , 4 ], [ 4 , 5 ]]
init(edges, 4 )
dfs_First( 0 )
for i in range ( 0 , n):
visited[i] = False
answer = False
if (cal_XOR[ 0 ] = = 0 ):
answer = True
else :
dfs_Second( 0 )
if (counter > = 2 and p ! = 2 ):
answer = True
if (answer = = True ):
print ( "YES" )
else :
print ( "NO" )
counter = 0
for i in range ( 0 , n):
adj[i] = []
cal_XOR[i] = nodes[i] = 0
|
C#
using System;
using System.Collections;
using System.Collections.Generic;
public class GFG
{
static List< int >[] adj = new List< int >[10000];
static int [] nodes = new int [10000];
static int [] cal_XOR = new int [10000];
static bool [] visited = new bool [10000];
static int counter = 0;
static int dfs_First( int x)
{
cal_XOR[x] = nodes[x];
visited[x] = true ;
for ( int i = 0; i < adj[x].Count; i++)
{
if (!visited[adj[x][i]])
{
cal_XOR[x] ^= dfs_First(adj[x][i]);
}
}
return cal_XOR[x];
}
static int dfs_Second( int x)
{
visited[x] = true ;
int temp = nodes[x];
for ( int i = 0; i < adj[x].Count; i++)
{
if (!visited[adj[x][i]])
{
temp ^= dfs_Second(adj[x][i]);
}
}
if (temp == cal_XOR[0])
{
temp = 0;
counter++;
}
return temp;
}
static void addEdge( int u, int v)
{
adj[u].Add(v);
adj[v].Add(u);
}
static void init( int [,] edges, int numEdges)
{
for ( int i = 0; i < numEdges; i++)
{
edges[i,0]--;
edges[i,1]--;
addEdge(edges[i,0], edges[i,1]);
}
}
public static void Main()
{
int n = 5, p = 2;
nodes[0] = 1;
nodes[1] = 6;
nodes[2] = 4;
nodes[3] = 1;
nodes[4] = 2;
for ( int i = 0; i < n; i++)
{
visited[i] = false ;
adj[i] = new List< int >();
}
int [,] edges = new int [4,2]
{ { 1, 2 }, { 2, 3 }, { 1, 4 }, { 4, 5 } };
init(edges, 4);
dfs_First(0);
for ( int i = 0; i < n; i++)
{
visited[i] = false ;
}
bool answer = false ;
if (cal_XOR[0] == 0)
{
answer = true ;
}
else
{
dfs_Second(0);
if (counter >= 2 && p != 2)
{
answer = true ;
}
}
if (answer == true )
Console.Write( "YES\n" );
else
Console.Write( "NO\n" );
counter = 0;
for ( int i = 0; i < n; i++)
{
adj[i].Clear();
cal_XOR[i] = nodes[i] = 0;
}
}
}
|
Javascript
<script>
let N = 1e5;
let adj = new Array(N);
for (let i = 0; i < N; i++) {
adj[i] = [];
}
let nodes = new Array(N), cal_XOR = new Array(N);
let visited = new Array(N).fill( false );
let counter = 0;
function dfs_First(x)
{
cal_XOR[x] = nodes[x];
visited[x] = true ;
for (let y of adj[x])
{
if (!visited[y])
{
cal_XOR[x] ^= dfs_First(y);
}
}
return cal_XOR[x];
}
function dfs_Second(x) {
visited[x] = true ;
let temp = nodes[x];
for (let y of adj[x]) {
if (!visited[y]) {
temp ^= dfs_Second(y);
}
}
if (temp == cal_XOR[0]) {
temp = 0;
counter++;
}
return temp;
}
function addEdge(u, v) {
adj[u].push(v);
adj[v].push(u);
}
function init(edges, numEdges) {
for (let i = 0; i < numEdges; i++) {
edges[i][0]--;
edges[i][1]--;
addEdge(edges[i][0], edges[i][1]);
}
}
let n = 5, p = 2;
nodes[0] = 1, nodes[1] = 6, nodes[2] = 4,
nodes[3] = 1, nodes[4] = 2;
for (let i = 0; i < n; i++) {
visited[i] = false ;
}
let edges =
[[1, 2], [2, 3], [1, 4], [4, 5]];
init(edges, 4);
dfs_First(0);
for (let i = 0; i < n; i++) {
visited[i] = false ;
}
let answer = false ;
if (cal_XOR[0] == 0) {
answer = true ;
}
else {
dfs_Second(0);
if (counter >= 2 && p != 2) {
answer = true ;
}
}
if (answer == true ) {
document.write( "YES" + '<br>' )
}
else {
document.write( "NO" + '<br>' )
}
counter = 0;
for (let i = 0; i < n; i++) {
adj[i] = [];
cal_XOR[i] = nodes[i] = 0;
}
</script>
|
Time Complexity: O(N+E), where N= number of nodes, and E = number of edges
Auxiliary Space: O(N+E), where N= number of nodes, and E = number of edges
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...