Open In App

Find MEX of every subtree in given Tree

Improve
Improve
Like Article
Like
Save
Share
Report

Given a Generic Tree consisting of N nodes numbered from 0 to N – 1 which is rooted at node 0 and an array val[] such that the value at each node is represented by val[i],  the task for each node is to find the value of MEX of its subtree.

The MEX value of node V is defined as the smallest missing positive number in a tree rooted at node V.

Examples:

Input: N = 6, edges = {{0, 1}, {1, 2}, {0, 3}, {3, 4}, {3, 5}}, val[] = {4, 3, 5, 1, 0, 2}
Output: [6, 0, 0, 3, 1, 0]
Explanation:
             0(4)
           /    \
      1(3)    3(1)
     /         /    \
2(5)     4(0)   5(2)  

In the subtrees of:
Node 0: All the values in range [0, 5] are present, hence the smallest non-negative value not present is 6.
Node 1: The smallest non-negative value not present in subtree of node 1 is 0.
Node 2: The smallest non-negative value not present in subtree of node 2 absent is 0.
Node 3: All the values in range [0, 2] are present, hence the smallest non-negative value not present in subtree of node 3 is 3.
Node 4: The smallest non-negative value not present in subtree of node 4 is 1.
Node 5: The smallest non-negative value not present in subtree of node 5 is 0.

Approach: The given problem can be solved using DFS Traversal on the given Tree and performing the Binary Search to find the missing minimum positive integers in each node subtree. Follow the steps below to solve the problem:

Below is the implementation of the above approach:

C++14




// C++ program for the above approach
 
#include <bits/stdc++.h>
using namespace std;
 
// Stores the edges of the tree
vector<vector<int> > edges;
 
// Function to add edges
void add_edge(int x, int y)
{
    edges.push_back({ x, y });
}
 
// Function to merge two sorted vectors
vector<int> merge(vector<int>& a,
                  vector<int>& b)
{
    // To store the result
    vector<int> res;
 
    int i = 0, j = 0;
    int n = a.size(), m = b.size();
 
    // Iterating both vectors
    while (i < n && j < m) {
        if (a[i] < b[j])
            res.push_back(a[i++]);
        else if (b[j] < a[i])
            res.push_back(b[j++]);
    }
 
    // Pushing remaining elements of
    // vector a
    while (i < n)
        res.push_back(a[i++]);
 
    // Pushing remaining elements of
    // vector b
    while (j < m)
        res.push_back(b[j++]);
 
    return res;
}
 
// Function to perform the DFS Traversal
// that returns the subtree of node
// in sorted manner
vector<int> help(vector<int> tree[], int x,
                 int p, vector<int>& c,
                 vector<int>& sol)
{
    vector<int> res;
    res.push_back(c[x]);
 
    // Iterate the childrens
    for (auto i : tree[x]) {
 
        // All values of subtree
        // i in sorted manner
        if (i != p) {
            vector<int> tmp
                = help(tree, i, x, c, sol);
            res = merge(res, tmp);
        }
    }
 
    int l = 0, r = res.size() - 1;
    int ans = res.size();
 
    // Binary search to find MEX
    while (l <= r) {
        // Find the mid
        int mid = (l + r) / 2;
 
        // Update the ranges
        if (res[mid] > mid)
            r = mid - 1;
        else {
            ans = mid + 1;
            l = mid + 1;
        }
    }
    if (res[0] != 0)
        ans = 0;
 
    // Update the MEX for the current
    // tree node
    sol[x] = ans;
 
    return res;
}
 
// Function to find MEX of each
// subtree of tree
void solve(int A, vector<int> C)
{
    int n = A;
    vector<int> tree[n + 1];
    for (auto i : edges) {
        tree[i[0]].push_back(i[1]);
        tree[i[1]].push_back(i[0]);
    }
    vector<int> sol(n, 0);
 
    // Function Call
    help(tree, 0, -1, C, sol);
 
    // Print the ans for each nodes
    for (auto i : sol)
        cout << i << " ";
}
 
// Driver Code
int main()
{
    int N = 6;
    add_edge(0, 1);
    add_edge(1, 2);
    add_edge(0, 3);
    add_edge(3, 4);
    add_edge(3, 5);
 
    vector<int> val = { 4, 3, 5, 1, 0, 2 };
    solve(N, val);
 
    return 0;
}


Java




// Java program for the above approach
 
import java.util.ArrayList;
import java.util.Arrays;
 
public class GFG {
 
    // Stores the edges of the tree
    static ArrayList<int[]> edges = new ArrayList<int[]>();
 
    // Function to add edges
    static void add_edge(int x, int y)
    {
        edges.add(new int[] { x, y });
    }
 
    // Function to merge two sorted vectors
    static ArrayList<Integer> merge(ArrayList<Integer> a,
                                    ArrayList<Integer> b)
    {
        // To store the result
        ArrayList<Integer> res = new ArrayList<Integer>();
 
        int i = 0, j = 0;
        int n = a.size(), m = b.size();
 
        // Iterating both vectors
        while (i < n && j < m) {
            if (a.get(i) < b.get(j))
                res.add(a.get(i++));
            else if (b.get(j) < a.get(i))
                res.add(b.get(j++));
        }
 
        // Pushing remaining elements of
        // vector a
        while (i < n)
            res.add(a.get(i++));
 
        // Pushing remaining elements of
        // vector b
        while (j < m)
            res.add(b.get(j++));
 
        return res;
    }
 
    // Function to perform the DFS Traversal
    // that returns the subtree of node
    // in sorted manner
    static ArrayList<Integer>
    help(ArrayList<Integer>[] tree, int x, int p, int[] c,
         int[] sol)
    {
        ArrayList<Integer> res = new ArrayList<Integer>();
        res.add(c[x]);
        // Iterate the childrens
        for (int i : tree[x]) {
 
            // All values of subtree
            // i in sorted manner
            if (i != p) {
                ArrayList<Integer> tmp
                    = help(tree, i, x, c, sol);
                res = merge(res, tmp);
            }
        }
 
        int l = 0, r = res.size() - 1;
        int ans = res.size();
 
        // Binary search to find MEX
        while (l <= r) {
            // Find the mid
            int mid = (l + r) / 2;
 
            // Update the ranges
            if (res.get(mid) > mid)
                r = mid - 1;
            else {
                ans = mid + 1;
                l = mid + 1;
            }
        }
        if (res.get(0) != 0)
            ans = 0;
 
        // Update the MEX for the current
        // tree node
        sol[x] = ans;
 
        return res;
    }
 
    // Function to find MEX of each
    // subtree of tree
      @SuppressWarnings("unchecked")
    static void solve(int A, int[] C)
    {
        int n = A;
        ArrayList<Integer>[] tree = new ArrayList[n + 1];
        for (int i = 0; i <= n; i++)
            tree[i] = new ArrayList<Integer>();
        for (int[] i : edges) {
            tree[i[0]].add(i[1]);
            tree[i[1]].add(i[0]);
        }
        int[] sol = new int[n];
 
        // Function Call
        help(tree, 0, -1, C, sol);
 
        // Print the ans for each nodes
        for (int i : sol)
            System.out.print(i + " ");
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        int N = 6;
        add_edge(0, 1);
        add_edge(1, 2);
        add_edge(0, 3);
        add_edge(3, 4);
        add_edge(3, 5);
 
        int[] val = { 4, 3, 5, 1, 0, 2 };
        solve(N, val);
    }
}
 
// This code is contributed by Lovely Jain


Python3




# Python code for the above approach
from typing import List
 
# Stores the edges of the tree
edges = []
 
# Function to add edges
def add_edge(x: int, y: int):
    edges.append([x, y])
 
# Function to merge two sorted lists
def merge(a: List[int], b: List[int]) -> List[int]:
    # To store the result
    res = []
 
    i, j = 0, 0
    n, m = len(a), len(b)
 
    # Iterating both lists
    while i < n and j < m:
        if a[i] < b[j]:
            res.append(a[i])
            i += 1
        elif b[j] < a[i]:
            res.append(b[j])
            j += 1
 
    # Pushing remaining elements of
    # list a
    while i < n:
        res.append(a[i])
        i += 1
 
    # Pushing remaining elements of
    # list b
    while j < m:
        res.append(b[j])
        j += 1
 
    return res
# Function to perform the DFS Traversal
# that returns the subtree of node
# in sorted manner (continued)
def help(tree: List[List[int]], x: int, p: int, c: List[int], sol: List[int]) -> List[int]:
    res = ]
 
    # Iterate the childrens
    for i in tree[x]:
        # All values of subtree
        # i in sorted manner
        if i != p:
            tmp = help(tree, i, x, c, sol)
            res = merge(res, tmp)
 
    l, r = 0, len(res) - 1
    ans = len(res)
 
    # Binary search to find MEX
    while l <= r:
        # Find the mid
        mid = (l + r) // 2
 
        # Update the ranges
        if res[mid] > mid:
            r = mid - 1
        else:
            ans = mid + 1
            l = mid + 1
 
    if res[0] != 0:
        ans = 0
 
    # Update the MEX for the current
    # tree node
    sol[x] = ans
 
    return res
 
# Function to find MEX of each
# subtree of tree
def solve(A: int, C: List[int]):
    n = A
    tree = [[] for _ in range(n + 1)]
    for i in edges:
        tree[i[0]].append(i[1])
        tree[i[1]].append(i[0])
    sol = [0] * n
 
    # Function Call
    help(tree, 0, -1, C, sol)
 
    # Print the ans for each nodes
    for i in sol:
        print(i, end=' ')
 
# Example usage
N = 6
add_edge(0, 1)
add_edge(1, 2)
add_edge(0, 3)
add_edge(3, 4)
add_edge(3, 5)
 
val = [4, 3, 5, 1, 0, 2]
solve(N, val)
 
# This code is contributed by Potta Lokesh


C#




// C# Equivalent Code
 
using System;
using System.Collections.Generic;
 
namespace GFG
{
    class Program
    {
        // Stores the edges of the tree
        static List<int[]> edges = new List<int[]>();
 
        // Function to add edges
        static void add_edge(int x, int y)
        {
            edges.Add(new int[] { x, y });
        }
 
        // Function to merge two sorted vectors
        static List<int> merge(List<int> a,
                               List<int> b)
        {
            // To store the result
            List<int> res = new List<int>();
 
            int i = 0, j = 0;
            int n = a.Count, m = b.Count;
 
            // Iterating both vectors
            while (i < n && j < m)
            {
                if (a[i] < b[j])
                    res.Add(a[i++]);
                else if (b[j] < a[i])
                    res.Add(b[j++]);
            }
 
            // Pushing remaining elements of
            // vector a
            while (i < n)
                res.Add(a[i++]);
 
            // Pushing remaining elements of
            // vector b
            while (j < m)
                res.Add(b[j++]);
 
            return res;
        }
 
        // Function to perform the DFS Traversal
        // that returns the subtree of node
        // in sorted manner
        static List<int> help(List<int>[] tree, int x, int p, int[] c,
                              int[] sol)
        {
            List<int> res = new List<int>();
            res.Add(c[x]);
            // Iterate the childrens
            foreach (int i in tree[x])
            {
                // All values of subtree
                // i in sorted manner
                if (i != p)
                {
                    List<int> tmp
                        = help(tree, i, x, c, sol);
                    res = merge(res, tmp);
                }
            }
 
            int l = 0, r = res.Count - 1;
            int ans = res.Count;
 
            // Binary search to find MEX
            while (l <= r)
            {
                // Find the mid
                int mid = (l + r) / 2;
 
                // Update the ranges
                if (res[mid] > mid)
                    r = mid - 1;
                else
                {
                    ans = mid + 1;
                    l = mid + 1;
                }
            }
            if (res[0] != 0)
                ans = 0;
 
            // Update the MEX for the current
            // tree node
            sol[x] = ans;
 
            return res;
        }
 
        // Function to find MEX of each
        // subtree of tree
        static void solve(int A, int[] C)
        {
            int n = A;
            List<int>[] tree = new List<int>[n + 1];
            for (int i = 0; i <= n; i++)
                tree[i] = new List<int>();
            foreach (int[] i in edges)
            {
                tree[i[0]].Add(i[1]);
                tree[i[1]].Add(i[0]);
            }
            int[] sol = new int[n];
 
            // Function Call
            help(tree, 0, -1, C, sol);
 
            // Print the ans for each nodes
            foreach (int i in sol)
                Console.Write(i + " ");
        }
 
        // Driver Code
        public static void Main(string[] args)
        {
            int N = 6;
            add_edge(0, 1);
            add_edge(1, 2);
            add_edge(0, 3);
            add_edge(3, 4);
            add_edge(3, 5);
 
            int[] val = { 4, 3, 5, 1, 0, 2 };
            solve(N, val);
        }
    }
}


Javascript




<script>
// Javascript program for the above approach
 
// Stores the edges of the tree
let edges = [];
 
// Function to add edges
function add_edge(x, y) {
  edges.push([x, y]);
}
 
// Function to merge two sorted vectors
function merge(a, b) {
  // To store the result
  let res = [];
 
  let i = 0,
    j = 0;
  let n = a.length,
    m = b.length;
 
  // Iterating both vectors
  while (i < n && j < m) {
    if (a[i] < b[j]) res.push(a[i++]);
    else if (b[j] < a[i]) res.push(b[j++]);
  }
 
  // Pushing remaining elements of
  // vector a
  while (i < n) res.push(a[i++]);
 
  // Pushing remaining elements of
  // vector b
  while (j < m) res.push(b[j++]);
 
  return res;
}
 
// Function to perform the DFS Traversal
// that returns the subtree of node
// in sorted manner
function help(tree, x, p, c, sol) {
  let res = [];
  res.push(c[x]);
 
  // Iterate the childrens
  for (let i of tree[x]) {
    // All values of subtree
    // i in sorted manner
    if (i != p) {
      let tmp = help(tree, i, x, c, sol);
      res = merge(res, tmp);
    }
  }
 
  let l = 0,
    r = res.length - 1;
  let ans = res.length;
 
  // Binary search to find MEX
  while (l <= r) {
    // Find the mid
    let mid = Math.floor((l + r) / 2);
 
    // Update the ranges
    if (res[mid] > mid) r = mid - 1;
    else {
      ans = mid + 1;
      l = mid + 1;
    }
  }
  if (res[0] != 0) ans = 0;
 
  // Update the MEX for the current
  // tree node
  sol[x] = ans;
 
  return res;
}
 
// Function to find MEX of each
// subtree of tree
function solve(A, C) {
  let n = A;
  let tree = new Array(n + 1).fill(0).map(() => []);
  for (let i of edges) {
    tree[i[0]].push(i[1]);
    tree[i[1]].push(i[0]);
  }
  let sol = new Array(n).fill(0);
 
  // Function Call
  help(tree, 0, -1, C, sol);
 
  // Print the ans for each nodes
  for (let i of sol) document.write(i + " ");
}
 
// Driver Code
 
let N = 6;
add_edge(0, 1);
add_edge(1, 2);
add_edge(0, 3);
add_edge(3, 4);
add_edge(3, 5);
 
let val = [4, 3, 5, 1, 0, 2];
solve(N, val);
 
// This code is contributed by _saurabh_jaiswal.
</script>


Output

6 0 0 3 1 0

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



Last Updated : 31 Oct, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads