Subárboles formados después de reventar Nodes

Se le da un árbol n-ario con una propiedad especial : 
si rompemos un Node aleatorio del árbol, este Node junto con sus padres inmediatos hasta la raíz se desvanece. El árbol tiene N Nodes y los Nodes están numerados del 1 al N. La raíz siempre está en 1. Dada una secuencia de consultas que indica el número del Node que comenzamos a explotar, el problema es encontrar el número de subárboles que se formarían en el final de acuerdo con la propiedad anterior, para cada consulta de forma independiente. 

Ejemplos:  

Input:
Consider the following tree:
             1
           / | \ 
          2  3  4
            / \   \
           5   6   7
                  / \
                 8   9

q = 2
n = 1  
n = 7   
Output:
3
4
Explanation:
In the first query after bursting node 1, there 
will be 3 subtrees formed rooted at 2, 3 and 4.
In the second query after bursting node 7, nodes 
4 and 1 also get burst, thus there will 
be 4 subtrees formed rooted at 8, 9, 2 and 3.

Como estamos tratando con un árbol n-ario, podemos usar una representación similar a la de un gráfico y agregar los bordes bidireccionales en una array de listas. Ahora, si rompemos un Node, podemos decir con seguridad que todos sus hijos se convertirán en subárboles separados. Además, todos los hijos de sus padres y otros antepasados ​​hasta la raíz que estalló, también se convertirán en subárboles separados. Entonces, en nuestra respuesta final, queremos excluir el Node actual y todos sus ancestros en el camino hasta la raíz. Así podemos formar la ecuación a resolver como:

respuesta[Node] = grado[Node] + allChild[padre[Node]] – countPath[Node] 
where allChild[]: número de hijos del Node + número de hijos de su 
padre + ..+ número de hijos de la raíz 
padre[]: padre de un Node en el árbol 
grado[]: número de hijos para un Node 
rutacuenta[]: número de Nodes desde la raíz hasta el padre del Node

Podemos llenar todas las arrays anteriores utilizando la búsqueda en profundidad primero en la lista de adyacencia. Podemos comenzar desde la raíz 1, asumiendo que su padre es 0 y repetir la profundidad primero para propagar sus valores a sus hijos. Por lo tanto, podemos preprocesar y llenar las arrays anteriores inicialmente y devolver el valor de la ecuación para cada consulta en consecuencia.

La siguiente es la implementación del enfoque anterior:

C++

// C++ program to find number of subtrees after bursting nodes
#include <bits/stdc++.h>
using namespace std;
 
// do depth first search of node nod; par is its parent
void dfs(int nod, int par, list<int> adj[], int allChild[],
         int parent[], int degree[], int countPath[])
{
    // go through the adjacent nodes
    for (auto it = adj[nod].begin(); it != adj[nod].end(); it++) {
        int curr = *it;
 
        // avoid cycling
        if (curr == par)
            continue;
 
        degree[nod]++;
        countPath[curr] = countPath[nod] + 1;
        parent[curr] = nod;
    }
 
    // propagated from parent
    allChild[nod] = allChild[parent[nod]] + degree[nod];
 
    // go through the adjacent nodes
    for (auto it = adj[nod].begin(); it != adj[nod].end(); it++) {
        int curr = *it;
 
        // avoid cycling
        if (curr == par)
            continue;
 
        // recur and go depth first
        dfs(curr, nod, adj, allChild, parent, degree, countPath);
    }
}
 
// Driver code
int main()
{
    int n = 9;
 
    // adjacency list for each node
    list<int> adj[n + 1];
 
    // allChild[]: number of node's children + number of its
    // parent's children + ..+ number of root's children
    // parent[]: parent of a node in the tree
    // degree[]: number of children for a node
    // countPath[]: number of nodes from root to parent of node
    int allChild[n + 1] = { 0 }, parent[n + 1] = { 0 },
       degree[n + 1] = { 0 }, countPath[n + 1] = { 0 };
 
    // construct tree
    adj[1].push_back(2);
    adj[2].push_back(1);
    adj[1].push_back(3);
    adj[3].push_back(1);
    adj[1].push_back(4);
    adj[4].push_back(1);
    adj[3].push_back(5);
    adj[5].push_back(3);
    adj[3].push_back(6);
    adj[6].push_back(3);
    adj[4].push_back(7);
    adj[7].push_back(4);
    adj[7].push_back(8);
    adj[8].push_back(7);
    adj[7].push_back(9);
    adj[9].push_back(7);
 
    // assume 1 is root and 0 is its parent
    dfs(1, 0, adj, allChild, parent, degree, countPath);
 
    // 2 queries
    int curr = 1;
    cout << degree[curr] + allChild[parent[curr]] - countPath[curr] << endl;
 
    curr = 7;
    cout << degree[curr] + allChild[parent[curr]] - countPath[curr] << endl;
 
    return 0;
}

Java

// Java program to find number of subtrees
// after bursting nodes
import java.util.*;
 
class GFG{
 
// Do depth first search of node nod;
// par is its parent
static void dfs(int nod, int par,
                List<Integer> adj[],
                int allChild[],
                int parent[],
                int degree[],
                int countPath[])
{
     
    // Go through the adjacent nodes
    for(int it : adj[nod])
    {
        int curr = it;
 
        // astatic void cycling
        if (curr == par)
            continue;
 
        degree[nod]++;
        countPath[curr] = countPath[nod] + 1;
        parent[curr] = nod;
    }
 
    // Propagated from parent
    allChild[nod] = allChild[parent[nod]] +
                             degree[nod];
 
    // Go through the adjacent nodes
    for(int it : adj[nod])
    {
        int curr = it;
 
        // astatic void cycling
        if (curr == par)
            continue;
 
        // recur and go depth first
        dfs(curr, nod, adj, allChild,
            parent, degree, countPath);
    }
}
 
// Driver code
public static void main(String[] args)
{
    int n = 9;
 
    // Adjacency list for each node
    @SuppressWarnings("unchecked")
    List<Integer> []adj = new List[n + 1];
    for(int i = 0; i < adj.length; i++)
        adj[i] = new Vector<Integer>();
 
    // allChild[]: number of node's children +
    // number of its parent's children + ..+
    // number of root's children
    // parent[]: parent of a node in the tree
    // degree[]: number of children for a node
    // countPath[]: number of nodes from root
    // to parent of node
    int []allChild = new int[n + 1];
    int []parent = new int[n + 1];
    int []degree = new int[n + 1];
    int []countPath = new int[n + 1];
 
    // Contree
    adj[1].add(2);
    adj[2].add(1);
    adj[1].add(3);
    adj[3].add(1);
    adj[1].add(4);
    adj[4].add(1);
    adj[3].add(5);
    adj[5].add(3);
    adj[3].add(6);
    adj[6].add(3);
    adj[4].add(7);
    adj[7].add(4);
    adj[7].add(8);
    adj[8].add(7);
    adj[7].add(9);
    adj[9].add(7);
 
    // Assume 1 is root and 0 is its parent
    dfs(1, 0, adj, allChild, parent,
        degree, countPath);
 
    // 2 queries
    int curr = 1;
    System.out.print(degree[curr] +
            allChild[parent[curr]] -
                  countPath[curr] + "\n");
 
    curr = 7;
    System.out.print(degree[curr] +
            allChild[parent[curr]] -
                  countPath[curr] + "\n");
}
}
 
// This code is contributed by Amit Katiyar

Python3

# Python3 program to find number of
# subtrees after bursting nodes
 
# Do depth first search of node
# nod par is its parent
def dfs(nod, par, adj, allChild,
        parent, degree, countPath):
             
    # Go through the adjacent nodes
    for it in adj[nod]:
        curr = it
 
        # Avoid cycling
        if (curr == par):
            continue
 
        degree[nod] += 1
        countPath[curr] = countPath[nod] + 1
        parent[curr] = nod
 
    # Propagated from parent
    allChild[nod] = (allChild[parent[nod]] +
                     degree[nod])
 
    # Go through the adjacent nodes
    for it in adj[nod]:
        curr = it
 
        # Avoid cycling
        if (curr == par):
            continue
 
        # recur and go depth first
        dfs(curr, nod, adj, allChild,
            parent, degree, countPath)
 
# Driver code
if __name__ == '__main__':
 
    n = 9
     
    # Adjacency list for each node
    adj = [[] for i in range(n + 1)]
 
    # allChild: number of node's children + number of its
    # parent's children + ..+ number of root's children
    # parent: parent of a node in the tree
    # degree: number of children for a node
    # countPath: number of nodes from root to parent of node
    allChild, parent = [0] * (n + 1), [0] * (n + 1)
    degree, countPath = [0] * (n + 1), [0] * (n + 1)
 
    # Construct tree
    adj[1].append(2)
    adj[2].append(1)
    adj[1].append(3)
    adj[3].append(1)
    adj[1].append(4)
    adj[4].append(1)
    adj[3].append(5)
    adj[5].append(3)
    adj[3].append(6)
    adj[6].append(3)
    adj[4].append(7)
    adj[7].append(4)
    adj[7].append(8)
    adj[8].append(7)
    adj[7].append(9)
    adj[9].append(7)
 
    # Assume 1 is root and 0 is its parent
    dfs(1, 0, adj, allChild, parent,
        degree, countPath)
 
    # 2 queries
    curr = 1
    print(degree[curr] + allChild[parent[curr]] -
          countPath[curr])
 
    curr = 7
    print(degree[curr] + allChild[parent[curr]] -
          countPath[curr])
 
# This code is contributed by mohit kumar 29

C#

// C# program to find number of subtrees
// after bursting nodes
using System;
using System.Collections.Generic;
 
class GFG{
 
// Do depth first search of node nod;
// par is its parent
static void dfs(int nod, int par,
                List<int> []adj,
                int []allChild,
                int []parent,
                int []degree,
                int []countPath)
{
     
    // Go through the adjacent nodes
    foreach(int it in adj[nod])
    {
        int curr = it;
 
        // astatic void cycling
        if (curr == par)
            continue;
 
        degree[nod]++;
        countPath[curr] = countPath[nod] + 1;
        parent[curr] = nod;
    }
 
    // Propagated from parent
    allChild[nod] = allChild[parent[nod]] +
                             degree[nod];
 
    // Go through the adjacent nodes
    foreach(int it in adj[nod])
    {
        int curr = it;
 
        // astatic void cycling
        if (curr == par)
            continue;
 
        // recur and go depth first
        dfs(curr, nod, adj, allChild,
            parent, degree, countPath);
    }
}
 
// Driver code
public static void Main(String[] args)
{
    int n = 9;
 
    // Adjacency list for each node
    List<int> []adj = new List<int>[n + 1];
    for(int i = 0; i < adj.Length; i++)
        adj[i] = new List<int>();
 
    // allChild[]: number of node's children +
    // number of its parent's children + ..+
    // number of root's children
    // parent[]: parent of a node in the tree
    // degree[]: number of children for a node
    // countPath[]: number of nodes from root
    // to parent of node
    int []allChild = new int[n + 1];
    int []parent = new int[n + 1];
    int []degree = new int[n + 1];
    int []countPath = new int[n + 1];
 
    // Contree
    adj[1].Add(2);
    adj[2].Add(1);
    adj[1].Add(3);
    adj[3].Add(1);
    adj[1].Add(4);
    adj[4].Add(1);
    adj[3].Add(5);
    adj[5].Add(3);
    adj[3].Add(6);
    adj[6].Add(3);
    adj[4].Add(7);
    adj[7].Add(4);
    adj[7].Add(8);
    adj[8].Add(7);
    adj[7].Add(9);
    adj[9].Add(7);
 
    // Assume 1 is root and 0 is its parent
    dfs(1, 0, adj, allChild, parent,
        degree, countPath);
 
    // 2 queries
    int curr = 1;
    Console.Write(degree[curr] +
        allChild[parent[curr]] -
               countPath[curr] + "\n");
 
    curr = 7;
    Console.Write(degree[curr] +
        allChild[parent[curr]] -
               countPath[curr] + "\n");
}
}
 
// This code is contributed by Amit Katiyar

Javascript

<script>
// Javascript program to find number of subtrees
// after bursting nodes
     
    // Do depth first search of node nod;
// par is its parent
    function dfs(nod,par,adj,allChild,parent,degree,countPath)
    {
        // Go through the adjacent nodes
    for(let it=0;it<adj[nod].length;it++)
    {
        let curr = adj[nod][it];
  
        // astatic void cycling
        if (curr == par)
            continue;
  
        degree[nod]++;
        countPath[curr] = countPath[nod] + 1;
        parent[curr] = nod;
    }
  
    // Propagated from parent
    allChild[nod] = allChild[parent[nod]] +
                             degree[nod];
  
    // Go through the adjacent nodes
    for(let it=0;it<adj[nod].length;it++)
    {
        let curr = adj[nod][it];
  
        // astatic void cycling
        if (curr == par)
            continue;
  
        // recur and go depth first
        dfs(curr, nod, adj, allChild,
            parent, degree, countPath);
    }
    }
     
    // Driver code
    let n = 9;
  
    // Adjacency list for each node
    let adj = new Array(n + 1);
    for(let i = 0; i < adj.length; i++)
        adj[i] = [];
  
    // allChild[]: number of node's children +
    // number of its parent's children + ..+
    // number of root's children
    // parent[]: parent of a node in the tree
    // degree[]: number of children for a node
    // countPath[]: number of nodes from root
    // to parent of node
    let allChild = new Array(n + 1);
    let parent = new Array(n + 1);
    let degree = new Array(n + 1);
    let countPath = new Array(n + 1);
     for(let i=0;i<n+1;i++)
    {
        allChild[i]=0;
        parent[i]=0;
        degree[i]=0;
        countPath[i]=0;
    }
     
    // Contree
    adj[1].push(2);
    adj[2].push(1);
    adj[1].push(3);
    adj[3].push(1);
    adj[1].push(4);
    adj[4].push(1);
    adj[3].push(5);
    adj[5].push(3);
    adj[3].push(6);
    adj[6].push(3);
    adj[4].push(7);
    adj[7].push(4);
    adj[7].push(8);
    adj[8].push(7);
    adj[7].push(9);
    adj[9].push(7);
  
    // Assume 1 is root and 0 is its parent
    dfs(1, 0, adj, allChild, parent,
        degree, countPath);
  
    // 2 queries
    let curr = 1;
    document.write(degree[curr] +
            allChild[parent[curr]] -
                  countPath[curr] + "<br>");
  
    curr = 7;
    document.write(degree[curr] +
            allChild[parent[curr]] -
                  countPath[curr] + "<br>");
     
 
// This code is contributed by unknown2108
</script>
Producción

3
4

La complejidad temporal del algoritmo anterior es O(E * lg(V)) donde E id es el número de aristas y V es el número de vértices.

Publicación traducida automáticamente

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