Open In App

Minimum time required to visit all the special nodes of a Tree

Improve
Improve
Like Article
Like
Save
Share
Report

Given an undirected tree consisting of N vertices where some of the nodes are special nodes, the task is to visit all the special nodes from the root node in minimum time. Time for traveling from one node to another node can be assumed as unit time.

A node is special if the path from the root to the node consists of distinct value nodes.

Example: 

Input: N = 7, edges[] = {(0, 1), (0, 2), (1, 4), (1, 5), (2, 3), (2, 6)} 
isSpecial[] = {false, false, true, false, true, true, false} 
Output:
Explanation: 

Input: N = 7, edges[] = {(0, 1), (0, 2), (1, 4), (1, 5), (2, 3), (2, 6)} 
isSpecial[] = {false, false, true, false, false, true, false} 
Output:
Explanation: 

Approach: The idea is to use Depth First Search traversal and traverse the nodes. If any node is having a children which is a special node, add two to the steps required for that node. Also mark that node as a special node such that while moving up the steps are taken into consideration.

Below is the implementation of the above approach: 

C++




// C++ implementation to find
// the minimum time required to
// visit special nodes of a tree
 
#include <bits/stdc++.h>
using namespace std;
 
const int N = 100005;
 
// Time required to collect
vector<int> ans(N, 0);
 
vector<int> flag(N, 0);
 
// Minimum time required to reach
// all the special nodes of tree
void minimumTime(int u, int par,
                 vector<bool>& hasApple,
                 vector<int> adj[])
{
 
    // Condition to check if
    // the vertex has apple
    if (hasApple[u] == true)
        flag[u] = 1;
 
    // Iterate all the
    // adjacent of vertex u.
    for (auto it : adj[u]) {
 
        // if adjacent vertex
        // is it's parent
        if (it != par) {
            minimumTime(it, u, hasApple, adj);
 
            // if any vertex of subtree
            // it contain apple
            if (flag[it] > 0)
                ans[u] += (ans[it] + 2);
 
            // flagbit for node u
            // would be on if any vertex
            // in it's subtree contain apple
            flag[u] |= flag[it];
        }
    }
}
 
// Driver Code
int main()
{
    // Number of the vertex.
    int n = 7;
 
    vector<bool> hasApple{ false, false,
                           true, false,
                           true, true,
                           false };
 
    // Store all the edges,
    // any edge represented
    // by pair of vertex
    vector<pair<int, int> > edges;
 
    // Added all the
    // edge in edges vector.
    edges.push_back(make_pair(0, 1));
    edges.push_back(make_pair(0, 2));
    edges.push_back(make_pair(1, 4));
    edges.push_back(make_pair(1, 5));
    edges.push_back(make_pair(2, 3));
    edges.push_back(make_pair(2, 6));
 
    // Adjacent list
    vector<int> adj[n];
 
    for (int i = 0; i < edges.size(); i++) {
        int source_node = edges[i].first;
 
        int destination_node
            = edges[i].second;
 
        adj[source_node]
            .push_back(destination_node);
 
        adj[destination_node]
            .push_back(source_node);
    }
 
    // Function Call
    minimumTime(0, -1, hasApple, adj);
 
    cout << ans[0];
    return 0;
}


Java




// Java implementation to find
// the minimum time required to
// visit special nodes of a tree
import java.util.*;
 
@SuppressWarnings("unchecked")
public class GFG{
 
static class pair
{
    int first, second;
     
    pair(int first, int second)
    {
        this.first = first;
        this.second = second;
    }
}
 
static final int N = 100005;
  
// Time required to collect
static ArrayList ans;
static ArrayList flag;
  
// Minimum time required to reach
// all the special nodes of tree
static void minimumTime(int u, int par,
                        ArrayList hasApple,
                        ArrayList adj[])
{
     
    // Condition to check if
    // the vertex has apple
    if ((boolean)hasApple.get(u) == true)
        flag.set(u, 1);
  
    // Iterate all the
    // adjacent of vertex u.
    for(int it : (ArrayList<Integer>)adj[u])
    {
         
        // If adjacent vertex
        // is it's parent
        if (it != par)
        {
            minimumTime(it, u, hasApple, adj);
  
            // If any vertex of subtree
            // it contain apple
            if ((int)flag.get(it) > 0)
                ans.set(u, (int)ans.get(u) +
                           (int)ans.get(it) + 2 );
  
            // flagbit for node u
            // would be on if any vertex
            // in it's subtree contain apple
            flag.set(u, (int)flag.get(u) |
                        (int)flag.get(it));
        }
    }
}
  
// Driver Code
public static void main(String []args)
{
     
    // Number of the vertex.
    int n = 7;
 
    ans = new ArrayList();
    flag = new ArrayList();
     
    for(int i = 0; i < N; i++)
    {
        ans.add(0);
        flag.add(0);
    }
     
    ArrayList hasApple = new ArrayList();
    hasApple.add(false);
    hasApple.add(false);
    hasApple.add(true);
    hasApple.add(false);
    hasApple.add(true);
    hasApple.add(true);
    hasApple.add(false);
  
    // Store all the edges,
    // any edge represented
    // by pair of vertex
    ArrayList edges = new ArrayList();
  
    // Added all the edge in
    // edges vector.
    edges.add(new pair(0, 1));
    edges.add(new pair(0, 2));
    edges.add(new pair(1, 4));
    edges.add(new pair(1, 5));
    edges.add(new pair(2, 3));
    edges.add(new pair(2, 6));
  
    // Adjacent list
    ArrayList []adj = new ArrayList[n];
 
    for(int i = 0; i < n; i++)
    {
        adj[i] = new ArrayList();
    }
  
    for(int i = 0; i < edges.size(); i++)
    {
        int source_node = ((pair)edges.get(i)).first;
        int destination_node = ((pair)edges.get(i)).second;
  
        adj[source_node].add(destination_node);
        adj[destination_node].add(source_node);
    }
  
    // Function Call
    minimumTime(0, -1, hasApple, adj);
     
    System.out.print(ans.get(0));
}
}
 
// This code is contributed by pratham76


Python3




# Python3 implementation to find
# the minimum time required to
# visit special nodes of a tree
N = 100005
  
# Time required to collect
ans = [0 for i in range(N)]
flag = [0 for i in range(N)]
  
# Minimum time required to reach
# all the special nodes of tree
def minimumTime(u, par, hasApple, adj):
  
    # Condition to check if
    # the vertex has apple
    if (hasApple[u] == True):
        flag[u] = 1
  
    # Iterate all the
    # adjacent of vertex u.
    for it in adj[u]:
  
        # if adjacent vertex
        # is it's parent
        if (it != par):
            minimumTime(it, u, hasApple, adj)
  
            # if any vertex of subtree
            # it contain apple
            if (flag[it] > 0):
                ans[u] += (ans[it] + 2)
  
            # flagbit for node u
            # would be on if any vertex
            # in it's subtree contain apple
            flag[u] |= flag[it]
  
# Driver Code
if __name__=='__main__':
 
    # Number of the vertex.
    n = 7
  
    hasApple = [ False, False, True,
                 False, True, True, False ]
  
    # Store all the edges,
    # any edge represented
    # by pair of vertex
    edges = []
  
    # Added all the
    # edge in edges vector.
    edges.append([0, 1])
    edges.append([0, 2])
    edges.append([1, 4])
    edges.append([1, 5])
    edges.append([2, 3])
    edges.append([2, 6])
  
    # Adjacent list
    adj = [[] for i in range(n)]
     
    for i in range(len(edges)):
        source_node = edges[i][0]
         
        destination_node = edges[i][1]
  
        adj[source_node].append(destination_node)
        adj[destination_node].append(source_node)
     
    # Function Call
    minimumTime(0, -1, hasApple, adj);
     
    print(ans[0])
     
# This code is contributed by rutvik_56


C#




// C# implementation to find
// the minimum time required to
// visit special nodes of a tree
using System;
using System.Collections.Generic;
class GFG {
     
    static int N = 100005;
    
    // Time required to collect
    static int[] ans = new int[N];
    static int[] flag = new int[N];
  
    // Minimum time required to reach
    // all the special nodes of tree
    static void minimumTime(int u, int par,
                            List<bool> hasApple,
                            List<List<int>> adj)
    {
  
        // Condition to check if
        // the vertex has apple
        if (hasApple[u])
            flag[u] = 1;
  
        // Iterate all the
        // adjacent of vertex u.
        for(int it = 0; it < adj[u].Count; it++)
        {
  
            // If adjacent vertex
            // is it's parent
            if (adj[u][it] != par)
            {
                minimumTime(adj[u][it], u, hasApple, adj);
  
                // If any vertex of subtree
                // it contain apple
                if (flag[adj[u][it]] > 0)
                    ans[u] = ans[u] + ans[adj[u][it]] + 2 ;
  
                // flagbit for node u
                // would be on if any vertex
                // in it's subtree contain apple
                flag[u] = flag[u] | flag[adj[u][it]];
            }
        }
    }
     
  static void Main() {
    // Number of the vertex.
    int n = 7;
       
    List<bool> hasApple = new List<bool>();
    hasApple.Add(false);
    hasApple.Add(false);
    hasApple.Add(true);
    hasApple.Add(false);
    hasApple.Add(true);
    hasApple.Add(true);
    hasApple.Add(false);
    
    // Store all the edges,
    // any edge represented
    // by pair of vertex
    List<Tuple<int,int>> edges = new List<Tuple<int,int>>();
    
    // Added all the edge in
    // edges vector.
    edges.Add(new Tuple<int,int>(0, 1));
    edges.Add(new Tuple<int,int>(0, 2));
    edges.Add(new Tuple<int,int>(1, 4));
    edges.Add(new Tuple<int,int>(1, 5));
    edges.Add(new Tuple<int,int>(2, 3));
    edges.Add(new Tuple<int,int>(2, 6));
    
    // Adjacent list
    List<List<int>> adj = new List<List<int>>();
   
    for(int i = 0; i < n; i++)
    {
        adj.Add(new List<int>());
    }
    
    for(int i = 0; i < edges.Count; i++)
    {
        int source_node = edges[i].Item1;
        int destination_node = edges[i].Item2;
    
        adj[source_node].Add(destination_node);
        adj[destination_node].Add(source_node);
    }
    
    // Function Call
    minimumTime(0, -1, hasApple, adj);
       
    Console.Write(ans[0]);
  }
}
 
// This code is contributed by divyesh072019.


Javascript




<script>
 
    // JavaScript implementation to find
    // the minimum time required to
    // visit special nodes of a tree
     
    let N = 100005;
   
    // Time required to collect
    let ans = [];
    let flag = [];
 
    // Minimum time required to reach
    // all the special nodes of tree
    function minimumTime(u, par, hasApple, adj)
    {
 
        // Condition to check if
        // the vertex has apple
        if (hasApple[u] == true)
            flag[u] = 1;
 
        // Iterate all the
        // adjacent of vertex u.
        for(let it = 0; it < adj[u].length; it++)
        {
 
            // If adjacent vertex
            // is it's parent
            if (adj[u][it] != par)
            {
                minimumTime(adj[u][it], u, hasApple, adj);
 
                // If any vertex of subtree
                // it contain apple
                if (flag[adj[u][it]] > 0)
                    ans[u] = ans[u] + ans[adj[u][it]] + 2 ;
 
                // flagbit for node u
                // would be on if any vertex
                // in it's subtree contain apple
                flag[u] = flag[u] | flag[adj[u][it]];
            }
        }
    }
     
    // Number of the vertex.
    let n = 7;
  
    ans = [];
    flag = [];
      
    for(let i = 0; i < N; i++)
    {
        ans.push(0);
        flag.push(0);
    }
      
    let hasApple = [];
    hasApple.push(false);
    hasApple.push(false);
    hasApple.push(true);
    hasApple.push(false);
    hasApple.push(true);
    hasApple.push(true);
    hasApple.push(false);
   
    // Store all the edges,
    // any edge represented
    // by pair of vertex
    let edges = [];
   
    // Added all the edge in
    // edges vector.
    edges.push([0, 1]);
    edges.push([0, 2]);
    edges.push([1, 4]);
    edges.push([1, 5]);
    edges.push([2, 3]);
    edges.push([2, 6]);
   
    // Adjacent list
    let adj = new Array(n);
  
    for(let i = 0; i < n; i++)
    {
        adj[i] = [];
    }
   
    for(let i = 0; i < edges.length; i++)
    {
        let source_node = edges[i][0];
        let destination_node = edges[i][1];
   
        adj[source_node].push(destination_node);
        adj[destination_node].push(source_node);
    }
   
    // Function Call
    minimumTime(0, -1, hasApple, adj);
      
    document.write(ans[0]);
     
</script>


Output: 

8

 

Time complexity: O(n)
Auxiliary Space: O(n)

Approach: Using HashMap

 If there’s a special node – travel from the node to the root. So we need a map – child to parent. Do not travel the same path again – mark it as -1 in the map.

Below is the Implementation:

C++




// C++ implementation to find
// the minimum time required to
// visit special nodes of a tree
 
#include <bits/stdc++.h>
using namespace std;
 
int minimumTime(int n, vector<vector<int> >& edges,
                vector<bool>& isSpecial)
{
 
    // map to store child to parent
    unordered_map<int, int> m;
 
    // sort the edges vector
    sort(edges.begin(), edges.end());
 
    // push into map(child to parent)
    for (auto& edge : edges) {
        if (m.count(edge[1]) > 0)
            m[edge[0]] = edge[1];
        else
            m[edge[1]] = edge[0];
    }
 
    // create result
    int result = 0;
 
    // Traverse over isSpecial vector
    for (int i = 0; i < isSpecial.size(); ++i) {
        // if node is not special then continue
        if (!isSpecial[i])
            continue;
 
        // take current node as parent
        int parent = i;
 
        while (parent != 0 && m[parent] >= 0) {
            auto temp = m[parent];
            m[parent] = -1;
            parent = temp;
            result += 2;
        }
    }
 
    // return result
    return result;
}
 
int main()
{
 
    // Number of the vertex.
    int n = 7;
 
    vector<bool> isSpecial{ false, false, true, false,
                            truetruefalse };
 
    // Store all the edges,
    // any edge represented
    // by pair of vertex
    vector<vector<int> > edges
        = { { 0, 1 }, { 0, 2 }, { 1, 4 },
            { 1, 5 }, { 2, 3 }, { 2, 6 } };
 
    // Function Call
    cout << minimumTime(n, edges, isSpecial);
 
    return 0;
}


Java




// java implementation to find
// the minimum time required to
// visit special nodes of a tree
import java.util.*;
public class Main {
    static int minimumTime(int n, int[][] edges, boolean[] isSpecial) {
      // map to store child to parent
        Map<Integer, Integer> m = new HashMap<>();
        // sort with respect to child
        Arrays.sort(edges, (a, b) -> a[0] - b[0]);
          // push into map(child to parent)
        for (int[] edge : edges) {
            if (m.containsKey(edge[1])) {
                m.put(edge[0], edge[1]);
            } else {
                m.put(edge[1], edge[0]);
            }
        }
 
        int result = 0;
          // Traverse over isSpecial vector
        for (int i = 0; i < isSpecial.length; i++) {
            // if node is not special then continue
            if (!isSpecial[i]) {
                continue;
            }
            // taking current node as parent
            int parent = i;
            while (parent != 0 && m.get(parent) >= 0) {
                int temp = m.get(parent);
                m.put(parent, -1);
                parent = temp;
                result += 2;
            }
        }
        // return the result
        return result;
    }
 
    public static void main(String[] args) {
          // Number of vertex
        int n = 7;
        // Store all the edges,
           // any edge represented
           // by pair of vertex
        boolean[] isSpecial = {false, false, true, false, true, true, false};
        int[][] edges = {{0, 1}, {0, 2}, {1, 4}, {1, 5}, {2, 3}, {2, 6}};
        // Function call
        System.out.println(minimumTime(n, edges, isSpecial));
    }
}


Python3




from collections import defaultdict
 
def minimumTime(n, edges, isSpecial):
   
    # Create a dictionary to store the parent-child relationship
    m = defaultdict(int)
 
    # Sort the edges list
    edges.sort()
 
    # Add the parent-child relationship to the dictionary
    for edge in edges:
        if edge[1] in m:
            m[edge[0]] = edge[1]
        else:
            m[edge[1]] = edge[0]
 
    # Initialize the result
    result = 0
 
    # Traverse over the isSpecial list
    for i in range(len(isSpecial)):
        # If the node is not special, continue
        if not isSpecial[i]:
            continue
 
        # Take the current node as the parent
        parent = i
 
        # Traverse through the parent-child relationship
        while parent != 0 and m[parent] >= 0:
            temp = m[parent]
            m[parent] = -1
            parent = temp
            result += 2
 
    # Return the result
    return result
 
# Number of vertices
n = 7
 
# List of special nodes
isSpecial = [False, False, True, False, True, True, False]
 
# List of edges
edges = [[0, 1], [0, 2], [1, 4], [1, 5], [2, 3], [2, 6]]
 
# Call the function
print(minimumTime(n, edges, isSpecial))


C#




using System;
using System.Collections.Generic;
using System.Linq;
 
class Program {
 
  static int MinimumTime(int n, List<List<int>> edges, List<bool> isSpecial) {
 
    // Dictionary to store child to parent
    Dictionary<int, int> m = new Dictionary<int, int>();
 
    // Sort the edges list
    edges.Sort((a, b) => a[0].CompareTo(b[0]));
 
    // Push into dictionary (child to parent)
    foreach (var edge in edges) {
      if (m.ContainsKey(edge[1]))
        m[edge[0]] = edge[1];
      else
        m[edge[1]] = edge[0];
    }
 
    // Create result
    int result = 0;
 
    // Traverse over isSpecial list
    for (int i = 0; i < isSpecial.Count; i++) {
      // If node is not special then continue
      if (!isSpecial[i])
        continue;
 
      // Take current node as parent
      int parent = i;
 
      while (parent != 0 && m[parent] >= 0) {
        int temp = m[parent];
        m[parent] = -1;
        parent = temp;
        result += 2;
      }
    }
 
    // Return result
    return result;
  }
 
  static void Main() {
 
    // Number of vertices
    int n = 7;
 
    List<bool> isSpecial = new List<bool> { false, false, true, false, true, true, false };
 
    // Store all the edges,
    // any edge represented by a pair of vertices
    List<List<int>> edges = new List<List<int>> {
      new List<int> { 0, 1 },
      new List<int> { 0, 2 },
      new List<int> { 1, 4 },
      new List<int> { 1, 5 },
      new List<int> { 2, 3 },
      new List<int> { 2, 6 }
    };
 
    // Function call
    Console.WriteLine(MinimumTime(n, edges, isSpecial));
  }
}


Javascript




// JavaScript implementation to find the minimum time
// required to visit special nodes of a tree
 
const minimumTime = (n, edges, isSpecial) => {
  // map to store child to parent
  const m = new Map();
 
  // sort the edges array
  edges.sort((a, b) => a[0] - b[0]);
 
  // push into map(child to parent)
  edges.forEach(edge => {
    if (m.has(edge[1])) m.set(edge[0], edge[1]);
    else m.set(edge[1], edge[0]);
  });
 
  // create result
  let result = 0;
 
  // Traverse over isSpecial array
  for (let i = 0; i < isSpecial.length; i++) {
    // if node is not special then continue
    if (!isSpecial[i]) continue;
 
    // take current node as parent
    let parent = i;
 
    while (parent != 0 && m.get(parent) >= 0) {
      const temp = m.get(parent);
      m.set(parent, -1);
      parent = temp;
      result += 2;
    }
  }
 
  // return result
  return result;
};
 
// Number of the vertex.
const n = 7;
 
const isSpecial = [false, false, true, false, true, true, false];
 
// Store all the edges, any edge represented by pair of vertex
const edges = [[0, 1], [0, 2], [1, 4], [1, 5], [2, 3], [2, 6]];
 
// Function Call
console.log(minimumTime(n, edges, isSpecial));


Output

8

Time complexity: O(n Log n)
Auxiliary Space: O(n)



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