Open In App

# Traversal of tree with k jumps allowed between nodes of same height

There is a tree with N nodes and node 1 is the root node. Each node of the tree can contain fruit or not. Initially, you are at the root node and start climbing on the tree. You can jump from a node to any node at the same level(i.e. the height of nodes from the root are same), During climbing from root node you can only make maximum K jumps. (K < 20) Now you have to climb on the tree (from root node-> any leaf node) in such a way so that you can collect maximum no of fruits.

Example :

Input Tree
Number of Nodes N = 12
Number of jumps allowed : 2
Edges:
1 2
1 3
2 4
2 5
5 9
9 10
9 11
11 12
3 7
7 6
7 8
no of node having fruit(nf) : 8
Nodes Containing Fruits(lvn) : 2 4 5 7 8 9 11 12
Output: 7

Tree for above testcase :

Explanation:

Approach: The idea is to use DFS to create a Height Adjacency List of the Nodes and to store the parents. Then use another dfs to compute the maximum no of special nodes that can be reached using the following dp state:

```dp[current_node][j] = max( max{ dp[child_i][j], for all children of current_node },
max{ dp[node_at_same_height_i][j - 1],
for all nodes at same height as current_node} )```

Thus, dp[Root_Node][Total_no_of_Jumps] gives the answer to the problem.

Below is the implementation of the above approach :

## CPP

 `// Program to demonstrate tree traversal with``// ability to jump between nodes of same height``#include ``using` `namespace` `std;` `#define N 1000` `vector<``int``> H[N];` `// Arrays declaration``int` `Fruit[N];``int` `Parent[N];``int` `dp[N][20];` `// Function for DFS``void` `dfs1(vector<``int``> tree[], ``int` `s, ``int` `p, ``int` `h)``{``    ``Parent[s] = p;``    ``int` `i;``    ``H[h].push_back(s);``    ``for` `(i = 0; i < tree[s].size(); i++) {``        ``int` `v = tree[s][i];``        ``if` `(v != p)``            ``dfs1(tree, v, s, h + 1);``    ``}``}` `// Function for DFS``int` `dfs2(vector<``int``> tree[], ``int` `s, ``int` `p, ``int` `h, ``int` `j)``{``    ``int` `i;``    ``int` `ans = 0;``    ``if` `(dp[s][j] != -1)``        ``return` `dp[s][j];` `    ``// jump``    ``if` `(j > 0) {``        ``for` `(i = 0; i < H[h].size(); i++) {``            ``int` `v = H[h][i];``            ``if` `(v != s)``                ``ans = max(ans, dfs2(tree, v, Parent[v], h,``                                    ``j - 1));``        ``}``    ``}` `    ``// climb``    ``for` `(i = 0; i < tree[s].size(); i++) {``        ``int` `v = tree[s][i];``        ``if` `(v != p)``            ``ans = max(ans, dfs2(tree, v, s, h + 1, j));``    ``}` `    ``if` `(Fruit[s] == 1)``        ``ans++;``    ``dp[s][j] = ans;` `    ``return` `ans;``}` `// Function to calculate and``// return maximum number of fruits``int` `maxFruit(vector<``int``> tree[], ``int` `NodesWithFruits[],``             ``int` `n, ``int` `m, ``int` `k)``{``    ``// resetting dp table and Fruit array``    ``for` `(``int` `i = 0; i < N; i++) {``        ``for` `(``int` `j = 0; j < 20; j++)``            ``dp[i][j] = -1;``        ``Fruit[i] = 0;``    ``}` `    ``// This array is used to mark``    ``// which nodes contain Fruits``    ``for` `(``int` `i = 0; i < m; i++)``        ``Fruit[NodesWithFruits[i]] = 1;` `    ``dfs1(tree, 1, 0, 0);``    ``int` `ans = dfs2(tree, 1, 0, 0, k);` `    ``return` `ans;``}` `// Function to add Edge``void` `addEdge(vector<``int``> tree[], ``int` `u, ``int` `v)``{``    ``tree[u].push_back(v);``    ``tree[v].push_back(u);``}` `// Driver Code``int` `main()``{``    ``int` `n = 12; ``// Number of nodes``    ``int` `k = 2; ``// Number of allowed jumps` `    ``vector<``int``> tree[N];` `    ``// Edges``    ``addEdge(tree, 1, 2);``    ``addEdge(tree, 1, 3);``    ``addEdge(tree, 2, 4);``    ``addEdge(tree, 2, 5);``    ``addEdge(tree, 5, 9);``    ``addEdge(tree, 9, 10);``    ``addEdge(tree, 9, 11);``    ``addEdge(tree, 11, 12);``    ``addEdge(tree, 3, 7);``    ``addEdge(tree, 7, 6);``    ``addEdge(tree, 7, 8);` `    ``int` `NodesWithFruits[] = { 2, 4, 5, 7, 8, 9, 11, 12 };` `    ``// Number of nodes with fruits``    ``int` `m = ``sizeof``(NodesWithFruits)``            ``/ ``sizeof``(NodesWithFruits[0]);` `    ``int` `ans = maxFruit(tree, NodesWithFruits, n, m, k);` `    ``cout << ans << endl;` `    ``return` `0;``}`

## Java

 `// Program to demonstrate tree traversal with``// ability to jump between nodes of same height``import` `java.util.*;` `public` `class` `GFG {``    ``static` `int` `N;` `    ``static` `ArrayList > H;` `    ``// Arrays declaration``    ``static` `int``[] Fruit;``    ``static` `int``[] Parent;``    ``static` `int``[][] dp; ``//[N][20]` `    ``// Function for DFS``    ``static` `void` `dfs1(ArrayList > tree,``                     ``int` `s, ``int` `p, ``int` `h)``    ``{``        ``Parent[s] = p;``        ``int` `i;``        ``H.get(h).add(s);``        ``for` `(i = ``0``; i < tree.get(s).size(); i++) {``            ``int` `v = tree.get(s).get(i);``            ``if` `(v != p)``                ``dfs1(tree, v, s, h + ``1``);``        ``}``    ``}` `    ``// Function for DFS``    ``static` `int` `dfs2(ArrayList > tree,``                    ``int` `s, ``int` `p, ``int` `h, ``int` `j)``    ``{``        ``int` `i;``        ``int` `ans = ``0``;``        ``if` `(dp[s][j] != -``1``)``            ``return` `dp[s][j];` `        ``// jump``        ``if` `(j > ``0``) {``            ``for` `(i = ``0``; i < H.get(h).size(); i++) {``                ``int` `v = H.get(h).get(i);``                ``if` `(v != s)``                    ``ans = Math.max(``                        ``ans,``                        ``dfs2(tree, v, Parent[v], h, j - ``1``));``            ``}``        ``}` `        ``// climb``        ``for` `(i = ``0``; i < tree.get(s).size(); i++) {``            ``int` `v = tree.get(s).get(i);``            ``if` `(v != p)``                ``ans = Math.max(ans,``                               ``dfs2(tree, v, s, h + ``1``, j));``        ``}` `        ``if` `(Fruit[s] == ``1``)``            ``ans++;``        ``dp[s][j] = ans;` `        ``return` `ans;``    ``}` `    ``// Function to calculate and``    ``// return maximum number of fruits``    ``static` `int` `maxFruit(ArrayList > tree,``                        ``int` `NodesWithFruits[], ``int` `n, ``int` `m,``                        ``int` `k)``    ``{``        ``// resetting dp table and Fruit array``        ``for` `(``int` `i = ``0``; i < N; i++) {``            ``for` `(``int` `j = ``0``; j < ``20``; j++)``                ``dp[i][j] = -``1``;``            ``Fruit[i] = ``0``;``        ``}` `        ``// This array is used to mark``        ``// which nodes contain Fruits``        ``for` `(``int` `i = ``0``; i < m; i++)``            ``Fruit[NodesWithFruits[i]] = ``1``;` `        ``dfs1(tree, ``1``, ``0``, ``0``);``        ``int` `ans = dfs2(tree, ``1``, ``0``, ``0``, k);` `        ``return` `ans;``    ``}` `    ``// Function to add Edge``    ``static` `void` `addEdge(ArrayList > tree,``                        ``int` `u, ``int` `v)``    ``{``        ``tree.get(u).add(v);``        ``tree.get(v).add(u);``    ``}` `    ``public` `static` `void` `main(String[] args)``    ``{``        ``N = ``1000``;``        ``H = ``new` `ArrayList<>();``        ``Fruit = ``new` `int``[N];``        ``Parent = ``new` `int``[N];``        ``dp = ``new` `int``[N][``20``];` `        ``int` `n = ``12``; ``// Number of nodes``        ``int` `k = ``2``; ``// Number of allowed jumps` `        ``ArrayList > tree``            ``= ``new` `ArrayList<>();``        ``for` `(``int` `i = ``0``; i < N; i++) {``            ``tree.add(``new` `ArrayList<>());``            ``H.add(``new` `ArrayList<>());``        ``}``        ``// Edges``        ``addEdge(tree, ``1``, ``2``);``        ``addEdge(tree, ``1``, ``3``);``        ``addEdge(tree, ``2``, ``4``);``        ``addEdge(tree, ``2``, ``5``);``        ``addEdge(tree, ``5``, ``9``);``        ``addEdge(tree, ``9``, ``10``);``        ``addEdge(tree, ``9``, ``11``);``        ``addEdge(tree, ``11``, ``12``);``        ``addEdge(tree, ``3``, ``7``);``        ``addEdge(tree, ``7``, ``6``);``        ``addEdge(tree, ``7``, ``8``);` `        ``int` `NodesWithFruits[]``            ``= { ``2``, ``4``, ``5``, ``7``, ``8``, ``9``, ``11``, ``12` `};` `        ``// Number of nodes with fruits``        ``int` `m = NodesWithFruits.length;` `        ``int` `ans = maxFruit(tree, NodesWithFruits, n, m, k);` `        ``System.out.println(ans);``    ``}``}``// This code is contributed by karandeep1234`

## Python3

 `# Program to demonstrate tree traversal with``# ability to jump between nodes of same height``import` `sys` `N ``=` `1000` `H ``=` `[[] ``for` `_ ``in` `range``(N)]` `# Arrays declaration``Fruit ``=` `[``0``] ``*` `N``Parent ``=` `[``0``] ``*` `N``dp ``=` `[[``-``1``] ``*` `20` `for` `_ ``in` `range``(N)]` `# Function for DFS``def` `dfs1(tree, s, p, h):``    ``Parent[s] ``=` `p``    ``for` `i ``in` `range``(``len``(tree[s])):``        ``v ``=` `tree[s][i]``        ``if` `v !``=` `p:``            ``dfs1(tree, v, s, h ``+` `1``)``    ``H[h].append(s)` `# Function for DFS``def` `dfs2(tree, s, p, h, j):``    ``ans ``=` `0``    ``if` `dp[s][j] !``=` `-``1``:``        ``return` `dp[s][j]` `    ``# jump``    ``if` `j > ``0``:``        ``for` `i ``in` `range``(``len``(H[h])):``            ``v ``=` `H[h][i]``            ``if` `v !``=` `s:``                ``ans ``=` `max``(ans, dfs2(tree, v, Parent[v], h, j ``-` `1``))` `    ``# climb``    ``for` `i ``in` `range``(``len``(tree[s])):``        ``v ``=` `tree[s][i]``        ``if` `v !``=` `p:``            ``ans ``=` `max``(ans, dfs2(tree, v, s, h ``+` `1``, j))` `    ``if` `Fruit[s] ``=``=` `1``:``        ``ans ``+``=` `1``    ``dp[s][j] ``=` `ans` `    ``return` `ans` `# Function to calculate and``# return maximum number of fruits``def` `maxFruit(tree, NodesWithFruits, n, m, k):``    ``# resetting dp table and Fruit array``    ``for` `i ``in` `range``(N):``        ``for` `j ``in` `range``(``20``):``            ``dp[i][j] ``=` `-``1``        ``Fruit[i] ``=` `0` `    ``# This array is used to mark``    ``# which nodes contain Fruits``    ``for` `i ``in` `range``(m):``        ``Fruit[NodesWithFruits[i]] ``=` `1` `    ``dfs1(tree, ``1``, ``0``, ``0``)``    ``ans ``=` `dfs2(tree, ``1``, ``0``, ``0``, k)` `    ``return` `ans` `# Function to add Edge``def` `addEdge(tree, u, v):``    ``tree[u].append(v)``    ``tree[v].append(u)` `# Driver Code``if` `__name__ ``=``=` `'__main__'``:``    ``n ``=` `12`  `# Number of nodes``    ``k ``=` `2`  `# Number of allowed jumps` `    ``tree ``=` `[[] ``for` `_ ``in` `range``(N)]` `    ``# Edges``    ``addEdge(tree, ``1``, ``2``)``    ``addEdge(tree, ``1``, ``3``)``    ``addEdge(tree, ``2``, ``4``)``    ``addEdge(tree, ``2``, ``5``)``    ``addEdge(tree, ``5``, ``9``)``    ``addEdge(tree, ``9``, ``10``)``    ``addEdge(tree, ``9``, ``11``)``    ``addEdge(tree, ``11``, ``12``)``    ``addEdge(tree, ``3``, ``7``)``    ``addEdge(tree, ``7``, ``6``)``    ``addEdge(tree, ``7``, ``8``)` `    ``NodesWithFruits ``=` `[``2``, ``4``, ``5``, ``7``, ``8``, ``9``, ``11``, ``12``]``    ` `    ``# Number of nodes with fruits``    ``m ``=` `len``(NodesWithFruits)``    ``ans ``=` `maxFruit(tree, NodesWithFruits, n, m, k)``    ``print``(ans)``    ` `    ``# This code is contributed by sanjanasikarwar24`

## C#

 `// Program to demonstrate tree traversal with``// ability to jump between nodes of same height` `using` `System;``using` `System.Collections;``using` `System.Collections.Generic;` `public` `class` `GFG {``    ``static` `int` `N;` `    ``static` `List > H;` `    ``// Arrays declaration``    ``static` `int``[] Fruit;``    ``static` `int``[] Parent;``    ``static` `int``[, ] dp; ``//[N][20]` `    ``// Function for DFS``    ``static` `void` `dfs1(List > tree, ``int` `s, ``int` `p,``                     ``int` `h)``    ``{``        ``Parent[s] = p;``        ``int` `i;``        ``H[h].Add(s);``        ``for` `(i = 0; i < tree[s].Count; i++) {``            ``int` `v = tree[s][i];``            ``if` `(v != p)``                ``dfs1(tree, v, s, h + 1);``        ``}``    ``}` `    ``// Function for DFS``    ``static` `int` `dfs2(List > tree, ``int` `s, ``int` `p,``                    ``int` `h, ``int` `j)``    ``{``        ``int` `i;``        ``int` `ans = 0;``        ``if` `(dp[s, j] != -1)``            ``return` `dp[s, j];` `        ``// jump``        ``if` `(j > 0) {``            ``for` `(i = 0; i < H[h].Count; i++) {``                ``int` `v = H[h][i];``                ``if` `(v != s)``                    ``ans = Math.Max(``                        ``ans,``                        ``dfs2(tree, v, Parent[v], h, j - 1));``            ``}``        ``}` `        ``// climb``        ``for` `(i = 0; i < tree[s].Count; i++) {``            ``int` `v = tree[s][i];``            ``if` `(v != p)``                ``ans = Math.Max(ans,``                               ``dfs2(tree, v, s, h + 1, j));``        ``}` `        ``if` `(Fruit[s] == 1)``            ``ans++;``        ``dp[s, j] = ans;` `        ``return` `ans;``    ``}` `    ``// Function to calculate and``    ``// return maximum number of fruits``    ``static` `int` `maxFruit(List > tree,``                        ``int``[] NodesWithFruits, ``int` `n, ``int` `m,``                        ``int` `k)``    ``{``        ``// resetting dp table and Fruit array``        ``for` `(``int` `i = 0; i < N; i++) {``            ``for` `(``int` `j = 0; j < 20; j++)``                ``dp[i, j] = -1;``            ``Fruit[i] = 0;``        ``}` `        ``// This array is used to mark``        ``// which nodes contain Fruits``        ``for` `(``int` `i = 0; i < m; i++)``            ``Fruit[NodesWithFruits[i]] = 1;` `        ``dfs1(tree, 1, 0, 0);``        ``int` `ans = dfs2(tree, 1, 0, 0, k);` `        ``return` `ans;``    ``}` `    ``// Function to add Edge``    ``static` `void` `addEdge(List > tree, ``int` `u, ``int` `v)``    ``{``        ``tree[u].Add(v);``        ``tree[v].Add(u);``    ``}` `    ``public` `static` `void` `Main(``string``[] args)``    ``{``        ``N = 1000;``        ``H = ``new` `List >();``        ``Fruit = ``new` `int``[N];``        ``Parent = ``new` `int``[N];``        ``dp = ``new` `int``[N, 20];` `        ``int` `n = 12; ``// Number of nodes``        ``int` `k = 2; ``// Number of allowed jumps` `        ``List > tree = ``new` `List >();``        ``for` `(``int` `i = 0; i < N; i++) {``            ``tree.Add(``new` `List<``int``>());``            ``H.Add(``new` `List<``int``>());``        ``}``        ``// Edges``        ``addEdge(tree, 1, 2);``        ``addEdge(tree, 1, 3);``        ``addEdge(tree, 2, 4);``        ``addEdge(tree, 2, 5);``        ``addEdge(tree, 5, 9);``        ``addEdge(tree, 9, 10);``        ``addEdge(tree, 9, 11);``        ``addEdge(tree, 11, 12);``        ``addEdge(tree, 3, 7);``        ``addEdge(tree, 7, 6);``        ``addEdge(tree, 7, 8);` `        ``int``[] NodesWithFruits``            ``= { 2, 4, 5, 7, 8, 9, 11, 12 };` `        ``// Number of nodes with fruits``        ``int` `m = NodesWithFruits.Length;` `        ``int` `ans = maxFruit(tree, NodesWithFruits, n, m, k);` `        ``Console.WriteLine(ans);``    ``}``}` `// This code is contributed by Karandeep1234`

## Javascript

 `// Javascript code for the above approach``const N = 1000;` `let H = ``new` `Array(N);``for` `(let i = 0; i < N; i++) {``    ``H[i] = [];``}` `// Arrays declaration``let Fruit = ``new` `Array(N).fill(0);``let Parent = ``new` `Array(N).fill(0);``let dp = ``new` `Array(N);``for` `(let i = 0; i < N; i++) {``    ``dp[i] = ``new` `Array(20).fill(-1);``}` `// Function for DFS``function` `dfs1(tree, s, p, h) {``    ``Parent[s] = p;``    ``for` `(let i = 0; i < tree[s].length; i++) {``        ``let v = tree[s][i];``        ``if` `(v !== p) {``            ``dfs1(tree, v, s, h + 1);``        ``}``    ``}``    ``H[h].push(s);``}` `// Function for DFS``function` `dfs2(tree, s, p, h, j) {``    ``let ans = 0;``    ``if` `(dp[s][j] !== -1) {``        ``return` `dp[s][j];``    ``}` `    ``// jump``    ``if` `(j > 0) {``        ``for` `(let i = 0; i < H[h].length; i++) {``            ``let v = H[h][i];``            ``if` `(v !== s) {``                ``ans = Math.max(ans, dfs2(tree, v, Parent[v], h, j - 1));``            ``}``        ``}``    ``}` `    ``// climb``    ``for` `(let i = 0; i < tree[s].length; i++) {``        ``let v = tree[s][i];``        ``if` `(v !== p) {``            ``ans = Math.max(ans, dfs2(tree, v, s, h + 1, j));``        ``}``    ``}` `    ``if` `(Fruit[s] === 1) {``        ``ans += 1;``    ``}``    ``dp[s][j] = ans;` `    ``return` `ans;``}` `// Function to calculate and``// return maximum number of fruits``function` `maxFruit(tree, NodesWithFruits, n, m, k) {``    ``// resetting dp table and Fruit array``    ``for` `(let i = 0; i < N; i++) {``        ``for` `(let j = 0; j < 20; j++) {``            ``dp[i][j] = -1;``        ``}``        ``Fruit[i] = 0;``    ``}` `    ``// This array is used to mark``    ``// which nodes contain Fruits``    ``for` `(let i = 0; i < m; i++) {``        ``Fruit[NodesWithFruits[i]] = 1;``    ``}` `    ``dfs1(tree, 1, 0, 0);``    ``let ans = dfs2(tree, 1, 0, 0, k);` `    ``return` `ans;``}` `// Function to add Edge``function` `addEdge(tree, u, v) {``    ``tree[u].push(v);``    ``tree[v].push(u);``}` `// Driver Code` `    ``let n = 12; ``// Number of nodes``    ``let k = 2; ``// Number of allowed jumps``let tree = ``new` `Array(N);``for` `(let i = 0; i < N; i++) {``tree[i] = [];``}` `// Edges``addEdge(tree, 1, 2);``addEdge(tree, 1, 3);``addEdge(tree, 2, 4);``addEdge(tree, 2, 5);``addEdge(tree, 5, 9);``addEdge(tree, 9, 10);``addEdge(tree, 9, 11);``addEdge(tree, 11, 12);``addEdge(tree, 3, 7);``addEdge(tree, 7, 6);``addEdge(tree, 7, 8);` `let NodesWithFruits = [2, 4, 5, 7, 8, 9, 11, 12];` `// Number of nodes with fruits``let m = NodesWithFruits.length;``let ans = maxFruit(tree, NodesWithFruits, n, m, k);``console.log(ans);` `// This code is contributed by lokeshpotta20.`

Output

`7`

Complexity Analysis:

• Time Complexity: O(n*n*k) (worst case, eg: 2 level tree with the root having n-1 child nodes)
• Auxiliary Space: O(n)