Open In App

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

Improve
Improve
Like Article
Like
Save
Share
Report

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 <bits/stdc++.h>
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<ArrayList<Integer> > H;
 
    // Arrays declaration
    static int[] Fruit;
    static int[] Parent;
    static int[][] dp; //[N][20]
 
    // Function for DFS
    static void dfs1(ArrayList<ArrayList<Integer> > 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<ArrayList<Integer> > 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<ArrayList<Integer> > 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<ArrayList<Integer> > 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<ArrayList<Integer> > 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<List<int> > H;
 
    // Arrays declaration
    static int[] Fruit;
    static int[] Parent;
    static int[, ] dp; //[N][20]
 
    // Function for DFS
    static void dfs1(List<List<int> > 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<List<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].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<List<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
    static void addEdge(List<List<int> > tree, int u, int v)
    {
        tree[u].Add(v);
        tree[v].Add(u);
    }
 
    public static void Main(string[] args)
    {
        N = 1000;
        H = new List<List<int> >();
        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<List<int> > tree = new List<List<int> >();
        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)


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