Subtrees formed after bursting nodes
You are given an n-ary tree with a special property:
If we burst a random node of the tree, this node along with its immediate parents up to the root vanishes. The tree has N nodes and nodes are numbered from 1 to N. The root is always at 1. Given a sequence of queries denoting the number of the node we start bursting, the problem is to find the number of subtrees that would be formed in the end according to the above property, for each query independently.
Examples:
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.
Since we are dealing with n-ary tree we can use a representation similar to that of a graph, and add the bidirectional edges in an array of lists. Now if we burst a node, we can say for sure that all its children will become separate subtrees. Moreover all the children of its parents and others ancestors till the root that burst, will also become separate subtrees. So in our final answer we want to exclude the current node and all its ancestors in the path till the root. Thus we can form the equation to solve as:
answer[node] = degree[node] + allChild[parent[node]] – countPath[node]
where 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
We can fill all the above arrays using depth first search over the adjacency list.We can start from the root 1, assuming its parent is 0 and recur depth first to propagate its values to its children. Thus we can pre-process and fill the above arrays initially and return the equation’s value for each query accordingly.
Following is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
void dfs( int nod, int par, list< int > adj[], int allChild[],
int parent[], int degree[], int countPath[])
{
for ( auto it = adj[nod].begin(); it != adj[nod].end(); it++) {
int curr = *it;
if (curr == par)
continue ;
degree[nod]++;
countPath[curr] = countPath[nod] + 1;
parent[curr] = nod;
}
allChild[nod] = allChild[parent[nod]] + degree[nod];
for ( auto it = adj[nod].begin(); it != adj[nod].end(); it++) {
int curr = *it;
if (curr == par)
continue ;
dfs(curr, nod, adj, allChild, parent, degree, countPath);
}
}
int main()
{
int n = 9;
list< int > adj[n + 1];
int allChild[n + 1] = { 0 }, parent[n + 1] = { 0 },
degree[n + 1] = { 0 }, countPath[n + 1] = { 0 };
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);
dfs(1, 0, adj, allChild, parent, degree, countPath);
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
import java.util.*;
class GFG{
static void dfs( int nod, int par,
List<Integer> adj[],
int allChild[],
int parent[],
int degree[],
int countPath[])
{
for ( int it : adj[nod])
{
int curr = it;
if (curr == par)
continue ;
degree[nod]++;
countPath[curr] = countPath[nod] + 1 ;
parent[curr] = nod;
}
allChild[nod] = allChild[parent[nod]] +
degree[nod];
for ( int it : adj[nod])
{
int curr = it;
if (curr == par)
continue ;
dfs(curr, nod, adj, allChild,
parent, degree, countPath);
}
}
public static void main(String[] args)
{
int n = 9 ;
@SuppressWarnings ( "unchecked" )
List<Integer> []adj = new List[n + 1 ];
for ( int i = 0 ; i < adj.length; i++)
adj[i] = new Vector<Integer>();
int []allChild = new int [n + 1 ];
int []parent = new int [n + 1 ];
int []degree = new int [n + 1 ];
int []countPath = new int [n + 1 ];
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 );
dfs( 1 , 0 , adj, allChild, parent,
degree, countPath);
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" );
}
}
|
Python3
def dfs(nod, par, adj, allChild,
parent, degree, countPath):
for it in adj[nod]:
curr = it
if (curr = = par):
continue
degree[nod] + = 1
countPath[curr] = countPath[nod] + 1
parent[curr] = nod
allChild[nod] = (allChild[parent[nod]] +
degree[nod])
for it in adj[nod]:
curr = it
if (curr = = par):
continue
dfs(curr, nod, adj, allChild,
parent, degree, countPath)
if __name__ = = '__main__' :
n = 9
adj = [[] for i in range (n + 1 )]
allChild, parent = [ 0 ] * (n + 1 ), [ 0 ] * (n + 1 )
degree, countPath = [ 0 ] * (n + 1 ), [ 0 ] * (n + 1 )
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 )
dfs( 1 , 0 , adj, allChild, parent,
degree, countPath)
curr = 1
print (degree[curr] + allChild[parent[curr]] -
countPath[curr])
curr = 7
print (degree[curr] + allChild[parent[curr]] -
countPath[curr])
|
C#
using System;
using System.Collections.Generic;
class GFG{
static void dfs( int nod, int par,
List< int > []adj,
int []allChild,
int []parent,
int []degree,
int []countPath)
{
foreach ( int it in adj[nod])
{
int curr = it;
if (curr == par)
continue ;
degree[nod]++;
countPath[curr] = countPath[nod] + 1;
parent[curr] = nod;
}
allChild[nod] = allChild[parent[nod]] +
degree[nod];
foreach ( int it in adj[nod])
{
int curr = it;
if (curr == par)
continue ;
dfs(curr, nod, adj, allChild,
parent, degree, countPath);
}
}
public static void Main(String[] args)
{
int n = 9;
List< int > []adj = new List< int >[n + 1];
for ( int i = 0; i < adj.Length; i++)
adj[i] = new List< int >();
int []allChild = new int [n + 1];
int []parent = new int [n + 1];
int []degree = new int [n + 1];
int []countPath = new int [n + 1];
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);
dfs(1, 0, adj, allChild, parent,
degree, countPath);
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" );
}
}
|
Javascript
<script>
function dfs(nod,par,adj,allChild,parent,degree,countPath)
{
for (let it=0;it<adj[nod].length;it++)
{
let curr = adj[nod][it];
if (curr == par)
continue ;
degree[nod]++;
countPath[curr] = countPath[nod] + 1;
parent[curr] = nod;
}
allChild[nod] = allChild[parent[nod]] +
degree[nod];
for (let it=0;it<adj[nod].length;it++)
{
let curr = adj[nod][it];
if (curr == par)
continue ;
dfs(curr, nod, adj, allChild,
parent, degree, countPath);
}
}
let n = 9;
let adj = new Array(n + 1);
for (let i = 0; i < adj.length; i++)
adj[i] = [];
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;
}
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);
dfs(1, 0, adj, allChild, parent,
degree, countPath);
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>" );
</script>
|
The time complexity of the above algorithm is O(E * lg(V)) where E is the number of edges and V is the number of vertices.
Auxiliary Space: O(n) where n is the number of nodes.
Last Updated :
20 Mar, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...