# Find edge to be deleted from Tree to maximise product of XOR of components

• Last Updated : 06 Jun, 2022

Given a tree of having N nodes rooted at node 0, and an array val[] denoting the value at each node, the task is to find the maximum possible product of XOR of connected components after removing one edge from the tree and also the edge which is removed.

Note: If there are multiple edges that give the maximum value then print them all in any order.

Examples:

Input: edges[][] = { {0, 5}, {0, 4}, {5, 1}, {5, 3}, {5, 2} }, val[ ] = { 7, 15, 9, 1, 1, 12}
Output: max_xor_product = 66
Edges: {0, 5}
Explanation: If we delete an edge {0, 5} then the tree will divide into two components.
The XOR of the first component is (1^7) = 6.
And the XOR of the second component is ( 12^15^1^9) = 11.
The product of xor of those components is ( 6*11) = 66.
Similarly, if we delete an edge { 5, 1} tree again divide into two-component.
The XOR of the first component is ( 15 ) ( because it has only one node)
and XOR of the second component is ( 7^1^12^9^1) = 2.
And the product of XOR of those components is ( 15 * 2 ) = 30.
If this is repeated the maximum value of the product of XOR of components will be 66,
which can be achieved if we delete the edge {0, 5}.

See the image below to understand it better Input: edges[][] = { {0, 1}, {0, 2}}, val[ ]={ 17, 17, 17}
Output: max_xor_product = 0
Edges: {{0, 1}, {0, 2}}

Naive Approach: Delete each edge and traverse through components and take xor of values of nodes in those components, then do the product of xor, store the maximum value and the edge corresponding to that value.

Time Complexity: O(N*N)
Auxiliary Space: O(N)

Efficient Method: This problem can be solved by precomputing XOR of subtree of each node and using bitwise XOR property as follows:

If an edge of a tree is deleted, then the tree will always divide into two components. The XOR of one component will be same as the XOR of the subtree (say X) and the other component will have XOR = (total XOR of all nodes ^ X).
For each edge, consider it to be removed and then find the XOR of both the components (using above observation) and their product. Keep track of the maximum and removing which edge results in that.

Follow the illustration shown below for a better understanding.

Illustration:

Consider the first example given below
edges[][] = { {0, 5}, {0, 4}, {5, 1}, {5, 3}, {5, 2} }, val[ ] = { 7, 15, 9, 1, 1, 12}

Remove edge {0, 4}:
=> Two components are {1} and {7, 12, 15, 1, 9}
=> XOR values are 1 and 12
=> Product = 1*12 = 12

Remove edge {0, 5}:
=> Two components are {1, 7} and {12, 15, 1, 9}
=> XOR values are 6 and 11
=> Product = 6*11 = 66

Remove edge {5, 1}:
=> Two components are {1, 7, 12, 1, 9} and {15}
=> XOR values are 2 and 15
=> Product = 2*15 = 30

Remove edge {5, 2}:
=> Two components are {1, 7, 12, 15, 1} and {9}
=> XOR values are 4 and 9
=> Product = 4*9 = 36

Remove edge {5, 3}:
=> Two components are {1, 7, 12, 15, 9} and {1}
=> XOR values are 1 and 12
=> Product = 1*12 = 12

So the maximum value is 66 which is achieved when the edge {0, 5} is removed

Follow the below steps to solve this problem:

• Calculate the XOR of all given values of all tree nodes (say tot_xor)
• Create an array (say subtree_xor[])and store the bitwise xor of the subtree of ith node using DFS.
• Now travel through the tree using DFS and for each node:
• Consider the edge between current node and its parent is removed.
• The two components will be: current node with its subtree and the remaining of the tree.
• Calculate the bitwise xor of current node with its subtree and of the remaining tree as mentioned in the above observation.
• Find the product of the XOR values.
• Update maximum value and removed edges accordingly.
• Return the maximum value and the removed edges.

Below is the implementation of the above approach:

## C++

 `// C++ code to implement the approach`   `#include ` `using` `namespace` `std;` `const` `int` `mxx = 1e6 + 7;` `int` `subtree_xor[mxx];`   `unordered_map<``long` `long``,` `              ``vector > >` `    ``store;`   `// To add edges in tree` `void` `addEdge(vector<``int``> tree[], ``int` `u, ``int` `v)` `{` `    ``tree[u].push_back(v);` `    ``tree[v].push_back(u);` `}`   `// To precompute xor value of each subtree` `void` `dfs(vector<``int``> tree[], ``int` `val[],` `         ``int` `cur_node, ``int` `par)` `{` `    ``// assign value of current node` `    ``subtree_xor[cur_node] = val[cur_node];`   `    ``for` `(``auto``& child : tree[cur_node]) {` `        ``if` `(child == par)` `            ``continue``;` `        ``dfs(tree, val, child, cur_node);` `        ``// take xor of all child node` `        ``subtree_xor[cur_node]` `            ``^= subtree_xor[child];` `    ``}` `}`   `// To store all xor_product` `// and it's corresponding edges` `void` `store_xor_product(vector<``int``> tree[],` `                       ``int` `cur_node,` `                       ``int` `par, ``int` `tot_xor)` `{` `    ``for` `(``auto``& child : tree[cur_node]) {` `        ``if` `(child == par)` `            ``continue``;`   `        ``// Xor of first component` `        ``int` `first_comp_xor` `            ``= subtree_xor[child];`   `        ``// Xor of second component` `        ``int` `second_comp_xor` `            ``= tot_xor ^ first_comp_xor;`   `        ``// Product can exceed int range` `        ``// so store it in long long data type` `        ``long` `long` `xor_product` `            ``= first_comp_xor * 1LL` `              ``* second_comp_xor;`   `        ``// Store edges corresponding` `        ``// to its product` `        ``store[xor_product].push_back({ cur_node,` `                                       ``child });`   `        ``store_xor_product(tree, child,` `                          ``cur_node, tot_xor);` `    ``}` `}`   `// To print edges corresponding` `// to max_xor_product of components` `void` `print_edges(``long` `long` `mx_product)` `{` `    ``for` `(``auto` `edges : store[mx_product]) {` `        ``cout << edges.first << ``" "` `             ``<< edges.second << ``"\n"``;` `    ``}` `}`   `// Driver code` `int` `findVal(``int` `N, ``int` `val[],` `            ``vector >& edges)` `{` `    ``int` `tot_xor = 0;`   `    ``// Store the xor of all values` `    ``for` `(``int` `i = 0; i < N; i++)` `        ``tot_xor ^= val[i];`   `    ``vector<``int``> tree[N];`   `    ``// Create a tree from given edges` `    ``for` `(``int` `i = 0; i < N - 1; i++)` `        ``addEdge(tree, edges[i],` `                ``edges[i]);`   `    ``// Dfs travel to store subtree xor` `    ``dfs(tree, val, 0, -1);`   `    ``// To store edges corresponding` `    ``// to xor_product` `    ``store_xor_product(tree, 0, -1, tot_xor);`   `    ``// Find maximum xor_product` `    ``long` `long` `mx_product = -1;` `    ``for` `(``auto` `ele : store) {` `        ``long` `long` `cur_product = ele.first;` `        ``mx_product` `            ``= max(mx_product, cur_product);` `    ``}` `    ``return` `mx_product;` `}`   `// Driver code` `int` `main()` `{` `    ``int` `N = 6;` `    ``vector > edges = {` `        ``{ 0, 5 }, { 0, 4 }, { 5, 1 }, { 5, 3 }, { 5, 2 }` `    ``};`   `    ``int` `val[] = { 7, 15, 9, 1, 1, 12 };` `    ``int` `mx_product = findVal(N, val, edges);` `    ``cout << mx_product << ``"\n"``;`   `    ``// To print edges corresponding` `    ``// to maximum xor_product` `    ``print_edges(mx_product);` `    ``return` `0;` `}`

## Java

 `// Java code for the above approach:` `import` `java.util.*;`   `public` `class` `Main {` `  ``static` `int` `mxx = ``1000007``;` `  ``static` `int` `subtree_xor[];` `  ``static` `HashMap > store;` `  ``static` `class` `IntPair {` `    ``int` `first;` `    ``int` `second;` `    ``IntPair(``int` `x, ``int` `y) {` `      ``this``.first = x;` `      ``this``.second = y;` `    ``}` `  ``}` `  ``// To add edges in tree` `  ``static` `void` `addEdge(ArrayList > tree, ``int` `u, ``int` `v)` `  ``{` `    ``tree.get(u).add(v);` `    ``tree.get(v).add(u);` `  ``}`   `  ``// To precompute xor value of each subtree` `  ``static` `void` `dfs(ArrayList > tree, ``int` `val[],` `                  ``int` `cur_node, ``int` `par)` `  ``{` `    ``// assign value of current node` `    ``subtree_xor[cur_node] = val[cur_node];`   `    ``for` `(Integer child : tree.get(cur_node)) {` `      ``if` `(child == par)` `        ``continue``;` `      ``dfs(tree, val, child, cur_node);` `      ``// take xor of all child node` `      ``subtree_xor[cur_node]` `        ``^= subtree_xor[child];` `    ``}` `  ``}`   `  ``// To store all xor_product` `  ``// and it's corresponding edges` `  ``static` `void` `store_xor_product(ArrayList > tree,` `                                ``int` `cur_node,` `                                ``int` `par, ``int` `tot_xor)` `  ``{` `    ``for` `(Integer child : tree.get(cur_node)) {` `      ``if` `(child == par)` `        ``continue``;`   `      ``// Xor of first component` `      ``long` `first_comp_xor` `        ``= subtree_xor[child];`   `      ``// Xor of second component` `      ``long` `second_comp_xor` `        ``= tot_xor ^ first_comp_xor;`   `      ``// Product can exceed int range` `      ``// so store it in long long data type` `      ``long` `xor_product` `        ``= first_comp_xor * second_comp_xor;`   `      ``// Store edges corresponding` `      ``// to its product` `      ``if``( ! store.containsKey(xor_product) ){` `        ``store.put(xor_product,``new` `ArrayList ());` `      ``}` `      ``store.get(xor_product).add(``new` `IntPair(cur_node, child) );`   `      ``store_xor_product(tree, child,` `                        ``cur_node, tot_xor);` `    ``}` `  ``}`   `  ``// To print edges corresponding` `  ``// to max_xor_product of components` `  ``static` `void` `print_edges(``long` `mx_product)` `  ``{` `    ``if``(store.containsKey(mx_product) ) {` `      ``for` `(IntPair edges : store.get(mx_product) ) {` `        ``System.out.println(edges.first + ``" "` `                           ``+ edges.second );` `      ``}` `    ``}` `  ``}`   `  ``static` `long` `findVal(``int` `N, ``int` `val[],` `                      ``int``[][] edges)` `  ``{` `    ``int` `tot_xor = ``0``;`   `    ``// Store the xor of all values` `    ``for` `(``int` `i = ``0``; i < N; i++)` `      ``tot_xor ^= val[i];` `    ``ArrayList > tree =` `      ``new` `ArrayList > (N);` `    ``for``(``int` `i = ``0``; i < N; i++){` `      ``tree.add(``new` `ArrayList ());` `    ``}`   `    ``// Create a tree from given edges` `    ``for` `(``int` `i = ``0``; i < N - ``1``; i++)` `      ``addEdge(tree, edges[i][``0``],` `              ``edges[i][``1``]);`   `    ``// Dfs travel to store subtree xor` `    ``dfs(tree, val, ``0``, -``1``);`   `    ``// To store edges corresponding` `    ``// to xor_product` `    ``store_xor_product(tree, ``0``, -``1``, tot_xor);`   `    ``// Find maximum xor_product` `    ``long` `mx_product = -``1``;` `    ``for` `(HashMap.Entry < Long, ArrayList > ele : store.entrySet()) {` `      ``long` `cur_product = ele.getKey();` `      ``mx_product` `        ``= Math.max(mx_product, cur_product);` `    ``}` `    ``return` `mx_product;` `  ``}`   `  ``// Driver Code` `  ``public` `static` `void` `main(String args[]) {` `    ``int` `N = ``6``;` `    ``int``[][] edges = {` `      ``{ ``0``, ``5` `}, { ``0``, ``4` `}, { ``5``, ``1` `}, { ``5``, ``3` `}, { ``5``, ``2` `}` `    ``};` `    ``subtree_xor = ``new` `int``[mxx];` `    ``store = ``new` `HashMap > ();` `    ``int` `val[] = { ``7``, ``15``, ``9``, ``1``, ``1``, ``12` `};` `    ``long` `mx_product = findVal(N, val, edges);` `    ``System.out.println( mx_product);`   `    ``// To print edges corresponding` `    ``// to maximum xor_product` `    ``print_edges(mx_product);` `  ``}` `}`   `// This code is contributed by Sachin Sahara (sachin801)`

Output

```66
0 5```

Time Complexity: O( N )
Auxiliary Space: O( N )

My Personal Notes arrow_drop_up
Recommended Articles
Page :