Número de pares distintos de aristas de modo que divide ambos árboles en los mismos subconjuntos de Nodes

Dados dos árboles cada uno de N Nodes. Quitar un borde del árbol divide el árbol en dos subconjuntos.
Encuentre el número máximo total de aristas distintas (e1, e2): e1 del primer árbol y e2 del segundo árbol de modo que divida ambos árboles en subconjuntos con los mismos Nodes.
Ejemplos: 

Entrada : Igual que la figura anterior N = 6 
Árbol 1: {(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)} 
Árbol 2:{(1 , 2), (2, 3), (1, 6), (6, 5), (5, 4)} 
Salida:
Podemos eliminar el borde 3-4 en el primer gráfico y el borde 1-6 en el segundo grafico. 
Los subconjuntos serán {1, 2, 3} y {4, 5, 6}. 
Entrada: N = 4 
Árbol 1: {(1, 2), (1, 3), (1, 4)} 
Árbol 2: {(1, 2), (2, 4), (1, 3)} 
Salida :
Podemos seleccionar una arista 1-3 en el primer gráfico y 1-3 en el segundo gráfico. 
Los subconjuntos serán {3} y {1, 2, 4} para ambos gráficos. 
También podemos seleccionar una arista 1-4 en el primer gráfico y 2-4 en el segundo gráfico. 
Los subconjuntos serán {4} y {1, 2, 3} para ambos gráficos 

Acercarse : 

  • La idea es usar hashing en los árboles. Enraizaremos ambos árboles en el Node 1, luego asignaremos valores aleatorios a cada Node del árbol.
  • Haremos un dfs en el árbol y, supongamos que estamos en el Node x, mantendremos una variable 
    subtree[x] que almacenará el valor hash de todos los Nodes en su subtree.
  • Una vez que hicimos los dos pasos anteriores, solo nos queda almacenar el valor de cada subárbol de Nodes para ambos árboles que obtenemos.
  • Podemos usar un mapa desordenado para ello. El último paso es encontrar cuántos valores comunes de subtree[x] hay en ambos árboles.
  • Aumente el recuento de bordes distintos en +1 por cada valor común de subtree[x] para ambos árboles.

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

CPP

// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
 
const long long p = 97, MAX = 300005;
 
// This function checks whether
// a node is leaf node or not.
bool leaf1(long long NODE, long long int deg1[])
{
    if (deg1[NODE] == 1 and NODE != 1)
        return true;
    return false;
}
 
// This function calculates the Hash sum
// of all the children of a
// particular node for subtree 1
void dfs3(long long curr, long long par,
          vector<long long int> tree1[],
          long long int subtree1[], long long int deg1[],
          long long int node[])
{
    for (auto& child : tree1[curr]) {
        if (child == par)
            continue;
        dfs3(child, curr, tree1, subtree1, deg1, node);
    }
 
    // If the node is leaf node then
    // there is no child, so hash sum
    // will be same as the
    // hash value for the node.
    if (leaf1(curr, deg1) == true) {
        subtree1[curr] = node[curr];
        return;
    }
    long long sum = 0;
 
    // Else calculate hash sum of all the
    // children of a particular node, this is done
    // by iterating on all the children of a node.
    for (auto& child : tree1[curr]) {
        sum = sum + subtree1[child];
    }
 
    // store the hash value for
    // all the subtree of current node
    subtree1[curr] = node[curr] + sum;
    return;
}
 
// This function checks whether
// a node is leaf node or not.
bool leaf2(long long NODE, long long int deg2[])
{
    if (deg2[NODE] == 1 and NODE != 1)
        return true;
    return false;
}
 
// This function calculates the Hash
// sum of all the children of
// a particular node for subtree 2.
void dfs4(long long curr, long long par,
          vector<long long int> tree2[],
          long long int subtree2[], long long int deg2[],
          long long int node[])
{
    for (auto& child : tree2[curr]) {
        if (child == par)
            continue;
        dfs4(child, curr, tree2, subtree2, deg2, node);
    }
 
    // If the node is leaf node then
    // there is no child, so hash sum will be
    // same as the hash value for the node.
    if (leaf2(curr, deg2) == true) {
        subtree2[curr] = node[curr];
        return;
    }
    long long sum = 0;
 
    // Else calculate hash sum of all
    // the children of a particular node, this is
    // done by iterating on all the children of a node.
    for (auto& child : tree2[curr]) {
        sum = sum + subtree2[child];
    }
 
    // store the hash value for
    // all the subtree of current node
    subtree2[curr] = node[curr] + sum;
}
 
// Calculates x^y in logN time.
long long exp(long long x, long long y)
{
    if (y == 0)
        return 1;
    else if (y & 1)
        return x * exp(x, y / 2) * exp(x, y / 2);
    else
        return exp(x, y / 2) * exp(x, y / 2);
}
 
// This function helps in building the tree
void Insertt(vector<long long int> tree1[],
             vector<long long int> tree2[],
             long long int deg1[], long long int deg2[])
{
    // Building Tree 1
    tree1[1].push_back(2);
    tree1[2].push_back(1);
    tree1[2].push_back(3);
    tree1[3].push_back(2);
    tree1[3].push_back(4);
    tree1[4].push_back(3);
    tree1[4].push_back(5);
    tree1[5].push_back(4);
    tree1[5].push_back(6);
    tree1[6].push_back(5);
 
    // Since 6 is a leaf node for tree 1
    deg1[6] = 1;
 
    // Building Tree 2
    tree2[1].push_back(2);
    tree2[2].push_back(1);
    tree2[2].push_back(3);
    tree2[3].push_back(2);
    tree2[1].push_back(6);
    tree2[6].push_back(1);
    tree2[6].push_back(5);
    tree2[5].push_back(6);
    tree2[5].push_back(4);
    tree2[4].push_back(5);
 
    // since both 3 and 4 are leaf nodes of tree 2 .
    deg2[3] = 1;
    deg2[4] = 1;
}
 
// Function to make the hash values
void TakeHash(long long n, long long int node[])
{
    // Take a very high prime
    long long p = 97 * 13 * 19;
 
    // Initialize random values to each node .
    for (long long i = 1; i <= n; ++i) {
 
        // A good random function is
        // chosen for each node .
        long long val = (rand() * rand() * rand())
                        + rand() * rand() + rand();
        node[i] = val * p * rand() + p * 13 * 19 * rand() * rand() * 101 * p;
        p *= p;
        p *= p;
    }
}
 
// Function that returns the required answer
void solve(long long n, vector<long long int> tree1[],
           vector<long long int> tree2[], long long int subtree1[],
           long long int subtree2[], long long int deg1[],
           long long int deg2[], long long int node[])
{
    // Do dfs on both trees to
    // get subtree[x] for each node.
    dfs3(1, 0, tree1, subtree1, deg1, node);
    dfs4(1, 0, tree2, subtree2, deg2, node);
 
    // cnt_tree1 and cnt_tree2 is used
    // to store the count of all
    // the hashes of every node .
    unordered_map<long long, long long>
        cnt_tree1, cnt_tree2;
    vector<long long> values;
    for (long long i = 1; i <= n; ++i) {
        long long value1 = subtree1[i];
        long long value2 = subtree2[i];
 
        // Store the subtree value of tree 1
        // in a vector to compare it later
        // with subtree value of tree 2.
        values.push_back(value1);
 
        // increment the count of hash
        // value for a subtree of a node.
        cnt_tree1[value1]++;
        cnt_tree2[value2]++;
    }
 
    // Stores the sum of all the hash values
    // of children for root node of subtree 1.
    long long root_tree1 = subtree1[1];
    long long root_tree2 = subtree2[1];
 
    // Stores the sum of all the hash values
    // of children for root node of subtree 1.
    cnt_tree1[root_tree1] = 0;
    cnt_tree2[root_tree2] = 0;
    long long answer = 0;
    for (auto& x : values) {
 
        // Check if for a given hash value for
        // tree 1 is there any hash value which
        // matches to hash value of tree 2
        // If yes, then its possible to divide
        // the tree for this hash value
        // into two equal subsets.
        if (cnt_tree1[x] != 0 and cnt_tree2[x] != 0)
            ++answer;
    }
    cout << answer << endl;
}
 
// Driver Code
int main()
{
    vector<long long int> tree1[MAX], tree2[MAX];
    long long int node[MAX], deg1[MAX], deg2[MAX];
    long long int subtree1[MAX], subtree2[MAX];
    long long n = 6;
 
    // To generate a good random function
    srand(time(NULL));
    Insertt(tree1, tree2, deg1, deg2);
    TakeHash(n, node);
    solve(n, tree1, tree2, subtree1, subtree2, deg1, deg2, node);
 
    return 0;
}
Producción: 

1

 

Complejidad de tiempo : O(N) 

Publicación traducida automáticamente

Artículo escrito por ajourney 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 *