Encuentre el borde que se eliminará del árbol para maximizar el producto de XOR de los componentes

Dado un árbol que tiene N Nodes enraizados en el Node 0 y una array val[] que indica el valor en cada Node, la tarea es encontrar el producto máximo posible de XOR de componentes conectados después de eliminar un borde del árbol y también el borde que se elimina. 

Nota: si hay varios bordes que dan el valor máximo, imprímalos todos en cualquier orden.

Ejemplos: 

Entrada: bordes[][] = { {0, 5}, {0, 4}, {5, 1}, {5, 3}, {5, 2} }, val[ ] = { 7, 15, 9 , 1, 1, 12}
Salida: max_xor_product = 66
Aristas: {0, 5}
Explicación : si eliminamos una arista {0, 5} , el árbol se dividirá en dos componentes.  
El XOR del primer componente es (1^7) = 6. 
Y el XOR del segundo componente es ( 12^15^1^9) = 11. 
El producto de xor de esos componentes es ( 6*11) = 66 Del mismo modo ,
si eliminamos una arista {5, 1}, el árbol vuelve a dividirse en dos componentes. 
El XOR del primer componente es (15) (porque solo tiene un Node) 
y el XOR del segundo componente es (7^1^12^9^1) = 2. 
Y el producto de XOR de esos componentes es ( 15 * 2 ) = 30.
Si esto se repite el valor máximo del producto de XOR de componentes será 66,  
que se puede conseguir si eliminamos la arista {0, 5}.

Mira la imagen de abajo para entenderlo mejor

Entrada: bordes[][] = { {0, 1}, {0, 2}}, val[ ]={ 17, 17, 17}
Salida : max_xor_product = 0
Bordes: {{0, 1}, {0, 2}}

 

Enfoque ingenuo: elimine cada borde y recorra los componentes y tome xor de los valores de los Nodes en esos componentes, luego haga el producto de xor, almacene el valor máximo y el borde correspondiente a ese valor.

Complejidad temporal: O(N*N)
Espacio auxiliar: O(N)

Método eficiente: este problema se puede resolver precalculando el XOR del subárbol de cada Node y usando la propiedad XOR bit a bit de la siguiente manera:

Si se elimina un borde de un árbol, el árbol siempre se dividirá en dos componentes. El XOR de un componente será el mismo que el XOR del subárbol (digamos X) y el otro componente tendrá XOR = (XOR total de todos los Nodes ^ X).
Para cada borde, considere que se elimina y luego encuentre el XOR de ambos componentes (usando la observación anterior) y su producto. Mantenga un registro del máximo y elimine qué borde da como resultado eso.

Siga la ilustración que se muestra a continuación para una mejor comprensión.

Ilustración:

Considere el primer ejemplo dado a continuación
edge[][] = { {0, 5}, {0, 4}, {5, 1}, {5, 3}, {5, 2} }, val[ ] = { 7 , 15, 9, 1, 1, 12}

Eliminar borde {0, 4} :
        => Dos componentes son {1} y {7, 12, 15, 1, 9}
        => Los valores XOR son 1 y 12
        => Producto = 1*12 = 12

Eliminar borde {0, 5} :
        => Dos componentes son {1, 7} y {12, 15, 1, 9}
        => Los valores XOR son 6 y 11
        => Producto = 6*11 = 66

Eliminar borde {5, 1} :
        => Dos componentes son {1, 7, 12, 1, 9} y {15}
        => Los valores XOR son 2 y 15
        => Producto = 2*15 = 30

Eliminar borde {5, 2} :
        => Dos componentes son {1, 7, 12, 15, 1} y {9}
        => Los valores XOR son 4 y 9
        => Producto = 4*9 = 36

Eliminar borde {5, 3} :
        => Dos componentes son {1, 7, 12, 15, 9} y {1}
        => Los valores XOR son 1 y 12
        => Producto = 1*12 = 12

Entonces, el valor máximo es 66, que se logra cuando se elimina el borde {0, 5}

Siga los pasos a continuación para resolver este problema: 

  • Calcule el XOR de todos los valores dados de todos los Nodes del árbol (digamos tot_xor )
  • Cree una array (digamos subtree_xor[] ) y almacene el xor bit a bit del subárbol del Node i mediante DFS .
  • Ahora recorra el árbol usando DFS y para cada Node:
    • Considere que se elimina el borde entre el Node actual y su padre .
    • Los dos componentes serán: el Node actual con su subárbol y el resto del árbol.
    • Calcule el xor bit a bit del Node actual con su subárbol y del árbol restante como se menciona en la observación anterior.
    • Encuentre el producto de los valores XOR.
    • Actualice el valor máximo y los bordes eliminados en consecuencia.
  • Devuelve el valor máximo y los bordes eliminados.

A continuación se muestra la implementación del enfoque anterior: 

C++

// C++ code to implement the approach
 
#include <bits/stdc++.h>
using namespace std;
const int mxx = 1e6 + 7;
int subtree_xor[mxx];
 
unordered_map<long long,
              vector<pair<int, int> > >
    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<vector<int> >& 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][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 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<vector<int> > 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 <Long,
  ArrayList <IntPair > > 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 <ArrayList <Integer>> 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 <ArrayList <Integer>> 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 <ArrayList <Integer>> 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<IntPair> ());
      }
      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 <ArrayList <Integer> > tree =
      new ArrayList <ArrayList <Integer>> (N);
    for(int i = 0; i < N; i++){
      tree.add(new ArrayList <Integer>());
    }
 
    // 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 <IntPair> > 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 <Long, ArrayList <IntPair > > ();
    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)
Producción

66
0 5

Complejidad de Tiempo : O( N )
Espacio Auxiliar : O( N ) 

Publicación traducida automáticamente

Artículo escrito por patilnainesh911 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *