Given a generic tree consisting of N nodes and (N – 1) edges and an array of queries query[] of size Q consisting of the type {A, B}, the task for each query is to check whether the path length between two given nodes A and B is even or odd.
Examples:
Input: query[] = {{2, 4}, {4, 0}}
Output:
Odd
Even
Explanation:
For the 1st query A = 2 and B = 4. The path from A to B is 2 -> 0 -> 1 -> 3 -> 4 having a length of 5 i.e., Odd.
For the 2nd query A = 4 and B = 0. The path from A to B is 4 -> 3 -> 1 -> 0 having a length of 4 i.e., Even.
Approach: The given problem can be efficiently solved by converting the tree into a Bipartite Graph. It can be observed that if the given nodes A and B in a query are on the same side in the constructed bipartite graph, then the path length between A and B must be odd and if A and B are on different sides, then the path length must be odd. Below are the steps to follow:
- Traverse the given tree using the BFS Traversal.
- Divide all nodes into 2 sets such that all the two adjacent nodes in the tree are in different sets (i.e., 0 or 1). In order to do so, assign an alternating set number to each level during the BFS traversal by assigning the set number of current nodes = 1 XOR the number of the parent of the current node.
- After completing the above steps, traverse the given array of queries query[] and if the set number of both the nodes are the same, the path length of A to B is Odd. Otherwise, it is Even.
Below is the implementation of the above approach:
// C++ program for the above approach #include <bits/stdc++.h> using namespace std;
// Stores the input tree vector<vector< int > > adj(100000);
// Stores the set number of all nodes vector< int > setNum(100000);
// Function to add an edge in the tree void addEdge( int a1, int a2)
{ adj[a1].push_back(a2);
adj[a2].push_back(a1);
} // Function to convert the given tree // into a bipartite graph using BFS void toBipartite( int N)
{ // Set the set number to -1 for
// all node of the given tree
setNum.assign(N, -1);
// Stores the current node during
// the BFS traversal of the tree
queue< int > q;
// Initialize the set number of
// 1st node and enqueue it
q.push(0);
setNum[0] = 0;
// BFS traversal of the given tree
while (!q.empty()) {
// Current node
int v = q.front();
q.pop();
// Traverse over all neighbours
// of the current node
for ( int u : adj[v]) {
// If the set is not assigned
if (setNum[u] == -1) {
// Assign set number to node u
setNum[u] = setNum[v] ^ 1;
q.push(u);
}
}
}
} // Function to find if the path length // between node A and B is even or odd void pathLengthQuery( int A, int B)
{ // If the set number of both nodes is
// same, path length is odd else even
if (setNum[A] == setNum[B]) {
cout << "Odd" << endl;
}
else {
cout << "Even" << endl;
}
} // Driver Code int main()
{ int N = 7;
addEdge(0, 1);
addEdge(0, 2);
addEdge(1, 3);
addEdge(3, 4);
addEdge(3, 5);
addEdge(2, 6);
// Function to convert tree into
// bipartite
toBipartite(N);
pathLengthQuery(4, 2);
pathLengthQuery(0, 4);
return 0;
} |
// Java program for the above approach import java.io.*;
import java.util.*;
class GFG {
// Stores the input tree @SuppressWarnings ( "unchecked" )
static Vector<Integer> []adj = new Vector[ 100000 ];
// Stores the set number of all nodes static Vector<Integer> setNum = new Vector<Integer>( 100000 );
// Function to add an edge in the tree static void addEdge( int a1, int a2)
{ adj[a1].add(a2);
adj[a2].add(a1);
} // Function to convert the given tree // into a bipartite graph using BFS static void toBipartite( int N)
{ // Set the set number to -1 for
// all node of the given tree
for ( int i = 0 ; i < 100000 ; i++)
setNum.add(- 1 );
// Stores the current node during
// the BFS traversal of the tree
Queue<Integer> q
= new LinkedList<>();
// Initialize the set number of
// 1st node and enqueue it
q.add( 0 );
setNum.set( 0 , 0 );
// BFS traversal of the given tree
while (!q.isEmpty()) {
// Current node
int v = q.peek();
q.remove();
// Traverse over all neighbours
// of the current node
for ( int u : adj[v]) {
// If the set is not assigned
if (setNum.get(u) == - 1 ) {
// Assign set number to node u
setNum.set(u, setNum.get(v) ^ 1 );
q.add(u);
}
}
}
} // Function to find if the path length // between node A and B is even or odd static void pathLengthQuery( int A, int B)
{ // If the set number of both nodes is
// same, path length is odd else even
if (setNum.get(A) == setNum.get(B)) {
System.out.println( "Odd" );
}
else {
System.out.println( "Even" );
}
} // Driver Code public static void main (String[] args) {
for ( int i = 0 ; i < 100000 ; i++)
adj[i] = new Vector<Integer>();
int N = 7 ;
addEdge( 0 , 1 );
addEdge( 0 , 2 );
addEdge( 1 , 3 );
addEdge( 3 , 4 );
addEdge( 3 , 5 );
addEdge( 2 , 6 );
// Function to convert tree into
// bipartite
toBipartite(N);
pathLengthQuery( 4 , 2 );
pathLengthQuery( 0 , 4 );
} } // This code is contributed by Dharanendra L V. |
# Python program for the above approach from queue import Queue
# Stores the input tree adj = [[ 0 ] * 100000 ] * 100000
# Stores the set number of all nodes setNum = [ 0 ] * 100000
# Function to add an edge in the tree def addEdge(a1, a2):
adj[a1].append(a2);
adj[a2].append(a1);
# Function to convert the given tree # into a bipartite graph using BFS def toBipartite(N):
# Set the set number to -1 for
# all node of the given tree
for i in range ( 0 , N):
setNum[i] = - 1
# Stores the current node during
# the BFS traversal of the tree
q = Queue();
# Initialize the set number of
# 1st node and enqueue it
q.put( 0 );
setNum[ 0 ] = 0 ;
# BFS traversal of the given tree
while ( not q.empty()):
# Current node
v = q.queue[ 0 ];
q.get();
# Traverse over all neighbours
# of the current node
for u in adj[v]:
# If the set is not assigned
if (setNum[u] = = - 1 ):
# Assign set number to node u
setNum[u] = setNum[v] ^ 1 ;
q.put(u);
# Function to find if the path length # between node A and B is even or odd def pathLengthQuery(A, B):
# If the set number of both nodes is
# same, path length is odd else even
if (setNum[A] = = setNum[B]):
print ( "Odd" );
else :
print ( "Even" );
# Driver Code N = 7 ;
addEdge( 0 , 1 );
addEdge( 0 , 2 );
addEdge( 1 , 3 );
addEdge( 3 , 4 );
addEdge( 3 , 5 );
addEdge( 2 , 6 );
# Function to convert tree into
# bipartite
toBipartite(N); pathLengthQuery( 4 , 2 );
pathLengthQuery( 0 , 4 );
# This code is contributed by _saurabh_jaiswal. |
// C# program for the above approach using System;
using System.Collections.Generic;
public class GFG
{ // Stores the input tree static List< int > []adj = new List< int >[100000];
// Stores the set number of all nodes static List< int > setNum = new List< int >(100000);
// Function to add an edge in the tree static void addEdge( int a1, int a2)
{ adj[a1].Add(a2);
adj[a2].Add(a1);
} // Function to convert the given tree // into a bipartite graph using BFS static void toBipartite( int N)
{ // Set the set number to -1 for
// all node of the given tree
for ( int i = 0; i < 100000; i++)
setNum.Add(-1);
// Stores the current node during
// the BFS traversal of the tree
Queue< int > q
= new Queue< int >();
// Initialize the set number of
// 1st node and enqueue it
q.Enqueue(0);
setNum[0] = 0;
// BFS traversal of the given tree
while (q.Count!=0) {
// Current node
int v = q.Peek();
q.Dequeue();
// Traverse over all neighbours
// of the current node
foreach ( int u in adj[v]) {
// If the set is not assigned
if (setNum[u] == -1) {
// Assign set number to node u
setNum[u] = ( setNum[v] ^ 1);
q.Enqueue(u);
}
}
}
} // Function to find if the path length // between node A and B is even or odd static void pathLengthQuery( int A, int B)
{ // If the set number of both nodes is
// same, path length is odd else even
if (setNum[A] == setNum[B])
{
Console.WriteLine( "Odd" );
}
else
{
Console.WriteLine( "Even" );
}
} // Driver Code public static void Main(String[] args) {
for ( int i = 0; i < 100000; i++)
adj[i] = new List< int >();
int N = 7;
addEdge(0, 1);
addEdge(0, 2);
addEdge(1, 3);
addEdge(3, 4);
addEdge(3, 5);
addEdge(2, 6);
// Function to convert tree into
// bipartite
toBipartite(N);
pathLengthQuery(4, 2);
pathLengthQuery(0, 4);
} } // This code is contributed by shikhasingrajput |
<script> //JavaScript code for the above approach
// Stores the input tree
let adj = Array(100000).fill().map(() => []);
// Stores the set number of all nodes
let setNum = Array(100000).fill(-1);
// Function to add an edge in the tree
function addEdge(a1, a2) {
adj[a1].push(a2);
adj[a2].push(a1);
}
// Function to convert the given tree
// into a bipartite graph using BFS
function toBipartite(N) {
// Stores the current node during
// the BFS traversal of the tree
let q = [];
// Initialize the set number of
// 1st node and enqueue it
q.push(0);
setNum[0] = 0;
// BFS traversal of the given tree
while (q.length > 0) {
// Current node
let v = q[0];
q.shift();
// Traverse over all neighbors
// of the current node
for (let u of adj[v]) {
// If the set is not assigned
if (setNum[u] === -1) {
// Assign set number to node u
setNum[u] = setNum[v] ^ 1;
q.push(u);
}
}
}
}
// Function to find if the path length
// between node A and B is even or odd
function pathLengthQuery(A, B) {
// If the set number of both nodes is
// same, path length is odd else even
if (setNum[A] === setNum[B]) {
document.write( "Odd" );
} else {
document.write( "Even" );
}
}
// Driver Code
let N = 7;
addEdge(0, 1);
addEdge(0, 2);
addEdge(1, 3);
addEdge(3, 4);
addEdge(3, 5);
addEdge(2, 6);
// Function to convert tree into
// bipartite
toBipartite(N);
pathLengthQuery(4, 2);
pathLengthQuery(0, 4);
// This code is contributed by Potta Lokesh
</script>
|
Odd Even
Time Complexity: O(N + Q)
Auxiliary Space: O(N)