Open In App

Minimum cost such that path sum is at max K (Target Path Sum)

Last Updated : 06 Mar, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Given a rooted tree consisting of N vertices. The vertices are numbered from 0 to N-1, and the root is the vertex 0. You are also given a value array Arr: Arr0, Arr1,….., Arrn-1. You can do any of these moves any number of times:

  • Pick any node that is not root cut the edge between it and its parent and connect an edge between this node to the root. This move will cost 0 units.
  • Pick any node U and change its value with the value of any other node. This move will cost A.
  • Pick any node U and change its value with any non-negative integer. This move will cost B.

Find the minimum cost after which there is no path from the root to any node with a sum greater than K.

Note: Tree is given in form of parent array Par of size N where Par[I] denotes the parent of the ith node. In case ith node is root Par[i] = -1.

Examples:

Input: N=4, Par[] = {-1, 0, 1, 2}, Arr[] = {65, 2, 80, 4}, K = 8, A = 3, B = 1
Output: 2
Explanation: In one move we can pick node 3 and cut the edge between 2 and 3 and add an edge between 0 and 3, This will cost 0. Then we can pick node 0 and use third moves to update its value to 0. This will cost 1. And again we can pick node 2 and use third moves to update its value to 0. This will again cost 1. After this move, no subtree is left with sum > K. So the total cost will be 2.

Input: N = 2, Par[] = {-1, 0}, Arr[] = {36, 42}, K = 100, A = 30, B = 61
Output: 0
Explanation: There is no subtree with sum>k.

Illustration:

N=4, Par[] = {-1, 0, 1, 2}, Arr[] = {65, 2, 80, 4}, K = 8, A = 3, B = 1

0(65)
/
1(2)
/
2(80)
/
3(4)

Perform first step i.e. cut the edge from 2 and 3, append 3 to root(0). This will cost 0.

0(65)

/ \

(2)1 3(4)

/

2(80)

Now root itself having greater value than k i.e 65>8, change the value of root to 0, costing B(1). Total cost = 1.

0(0)

/ \

(2)1 3(4)

/

2(80)

Now right part is having value less than k. But left part is still exceeding k. Therefore changed 2(80) to 2(0) at a cost B. Total cost = 2

0(0)

/ \

(2)1 3(4)

/

2(0)

Hence, 2 is the minimum cost.

Approach: To solve the problem, follow the below idea:

The problem can be solved by exploring all the cases. It is clear that we should connect all the nodes directly to the root as it would minimize the path sum and the cost will also be 0. Now, we can get the minimum cost by solving for the below cases:

  • Case 1: Do not change the value of the root and replace all those node’s value whose path sum becomes greater than K(Arr[0] + Arr[node] > K) with the minimum value among all nodes. The total cost will be A * number of nodes whose values are changed.
  • Case 2: Do not change the value of the root and replace all those node’s value whose path sum becomes greater than K(Arr[0] + Arr[node] > K) with 0. The total cost will be B * number of nodes whose values are changed.
  • Case 3: Replace the value of the root with minimum value among all nodes and replace all those node’s value whose path sum becomes greater than K(Arr[0] + Arr[node] > K) with the minimum value among all nodes. The total cost will be A + A * number of nodes whose values are changed.
  • Case 4: Replace the value of the root with 0 and replace all those node’s value whose path sum becomes greater than K(Arr[0] + Arr[node] > K) with 0. The total cost will be B + min(A, B) * number of nodes whose values are changed.

We can return the minimum of the four cases to get the final answer.

Step-by-step algorithm:

  • Maintain a function helper(rootVal, nodeVal, cost) which returns the minimum cost to make the path sum at max K, where rootVal is the value of the root node, nodeVal is the updated value of the other nodes and cost is the cost for updating the value of a node.
  • Call helper() for all the above cases to get the most optimal answer.

Below is the implementation of the approach:

C++




// C++ Implementation
#include <bits/stdc++.h>
#define ll long long
using namespace std;
 
ll INF = 1e18;
// Function to modify values with given rootVal, nodeVal and
// cost
ll helper(int rootval, int nodeVal, int cost, int K,
          vector<int>& arr)
{
    ll res = 0;
    int n = arr.size();
    for (int i = 1; i < n; i++) {
        if (rootval + arr[i] <= K)
            continue;
        else if (rootval + nodeVal <= K)
            res += cost;
        else
            return INF;
    }
    return res;
}
 
long long solve(int n, vector<int>& Par, vector<int>& arr,
                int K, int A, int B)
{
    int minv = *min_element(arr.begin(), arr.end());
 
    // No change in value of root and all the nodes are
    // changed to minv with cost = A
    ll res = helper(arr[0], minv, A, K, arr);
 
    // No change in value of root and all the nodes are
    // changed to 0 with cost = B
    res = min(res, helper(arr[0], 0, B, K, arr));
 
    // Root's value is changed to minv and all the nodes are
    // changed to minv with cost = A
    res = min(res, A + helper(minv, minv, A, K, arr));
 
    // Root's value is changed to 0 and all the nodes are
    // changed to 0 with cost = min(A, B)
    res = min(res, B + helper(0, 0, min(A, B), K, arr));
 
    return res == INF ? -1 : res;
}
// Driver code
int main()
{
    int N = 4;
    vector<int> Par = { -1, 0, 1, 2 };
    vector<int> Arr = { 65, 2, 80, 4 };
    int K = 8;
    int A = 3;
    int B = 1;
 
    // Function call
    cout << solve(N, Par, Arr, K, A, B);
    return 0;
}


Java




// Java Implementation
 
import java.util.Collections;
import java.util.List;
 
class GFG {
 
    static final long INF = (long)(1e18);
    // Function to modify values with given rootVal,
    // nodeVal and cost
    static long helper(int rootval, int nodeVal, int cost,
                       int K, List<Integer> arr)
    {
        long res = 0;
        int n = arr.size();
 
        for (int i = 1; i < n; i++) {
            if (rootval + arr.get(i) <= K)
                continue;
            else if (rootval + nodeVal <= K)
                res += cost;
            else
                return INF;
        }
 
        return res;
    }
 
    static long solve(int n, List<Integer> Par,
                      List<Integer> arr, int K, int A,
                      int B)
    {
        int minv = Collections.min(arr);
 
        // No change in value of root and all the nodes are
        // changed to minv with cost = A
        long res = helper(arr.get(0), minv, A, K, arr);
 
        // No change in value of root and all the nodes are
        // changed to 0 with cost = B
        res = Math.min(res,
                       helper(arr.get(0), 0, B, K, arr));
 
        // Root's value is changed to minv and all the nodes
        // are changed to minv with cost = A
        res = Math.min(res,
                       A + helper(minv, minv, A, K, arr));
 
        // Root's value is changed to 0 and all the nodes
        // are changed to 0 with cost = min(A, B)
        res = Math.min(
            res, B + helper(0, 0, Math.min(A, B), K, arr));
 
        return res == INF ? -1 : res;
    }
    // Driver code
    public static void main(String[] args)
    {
        int N = 4;
        List<Integer> Par = List.of(-1, 0, 1, 2);
        List<Integer> Arr = List.of(65, 2, 80, 4);
        int K = 8;
        int A = 3;
        int B = 1;
 
        // Function call
        System.out.println(solve(N, Par, Arr, K, A, B));
    }
}
 
// This code is contributed by ragul21


C#




using System;
using System.Collections.Generic;
using System.Linq;
 
public class Program
{
    static long INF = (long)1e18;
 
    // Function to modify values with given rootVal, nodeVal and cost
    static long Helper(int rootVal, int nodeVal, int cost, int K, List<int> arr)
    {
        long res = 0;
        int n = arr.Count;
         
        for (int i = 1; i < n; i++)
        {
            if (rootVal + arr[i] <= K)
                continue;
            else if (rootVal + nodeVal <= K)
                res += cost;
            else
                return INF;
        }
        return res;
    }
 
    static long Solve(int n, List<int> Par, List<int> arr, int K, int A, int B)
    {
        int minv = arr.Min();
 
        // No change in value of root and all the nodes are
        // changed to minv with cost = A
        long res = Helper(arr[0], minv, A, K, arr);
 
        // No change in value of root and all the nodes are
        // changed to 0 with cost = B
        res = Math.Min(res, Helper(arr[0], 0, B, K, arr));
 
        // Root's value is changed to minv and all the nodes are
        // changed to minv with cost = A
        res = Math.Min(res, A + Helper(minv, minv, A, K, arr));
 
        // Root's value is changed to 0 and all the nodes are
        // changed to 0 with cost = min(A, B)
        res = Math.Min(res, B + Helper(0, 0, Math.Min(A, B), K, arr));
 
        return res == INF ? -1 : res;
    }
 
    // Driver code
    public static void Main()
    {
        int N = 4;
        List<int> Par = new List<int> { -1, 0, 1, 2 };
        List<int> Arr = new List<int> { 65, 2, 80, 4 };
        int K = 8;
        int A = 3;
        int B = 1;
 
        // Function call
        Console.WriteLine(Solve(N, Par, Arr, K, A, B));
    }
}
 
// This code is contributed by shivamgupta310570


Javascript




function helper(rootVal, nodeVal, cost, K, arr) {
    let res = 0;
    const n = arr.length;
 
    for (let i = 1; i < n; i++) {
        if (rootVal + arr[i] <= K) continue;
        else if (rootVal + nodeVal <= K) res += cost;
        else return Infinity;
    }
 
    return res;
}
 
function solve(n, Par, arr, K, A, B) {
    const minv = Math.min(...arr);
 
    // No change in value of root and all the nodes are changed to minv with cost = A
    let res = helper(arr[0], minv, A, K, arr);
 
    // No change in value of root and all the nodes are changed to 0 with cost = B
    res = Math.min(res, helper(arr[0], 0, B, K, arr));
 
    // Root's value is changed to minv and all the nodes are changed to minv with cost = A
    res = Math.min(res, A + helper(minv, minv, A, K, arr));
 
    // Root's value is changed to 0 and all the nodes are changed to 0 with cost = min(A, B)
    res = Math.min(res, B + helper(0, 0, Math.min(A, B), K, arr));
 
    return res === Infinity ? -1 : res;
}
 
// Example usage
const N = 4;
const Par = [-1, 0, 1, 2];
const Arr = [65, 2, 80, 4];
const K = 8;
const A = 3;
const B = 1;
 
console.log(solve(N, Par, Arr, K, A, B));


Python3




def helper(rootval, nodeVal, cost, K, arr):
    res = 0
    n = len(arr)
 
    for i in range(1, n):
        if rootval + arr[i] <= K:
            continue
        elif rootval + nodeVal <= K:
            res += cost
        else:
            return float('inf'# Using float('inf') as an equivalent to Java's Long.MAX_VALUE
 
    return res
 
def solve(n, Par, arr, K, A, B):
    minv = min(arr)
 
    # No change in value of root and all the nodes are changed to minv with cost = A
    res = helper(arr[0], minv, A, K, arr)
 
    # No change in value of root and all the nodes are changed to 0 with cost = B
    res = min(res, helper(arr[0], 0, B, K, arr))
 
    # Root's value is changed to minv and all the nodes are changed to minv with cost = A
    res = min(res, A + helper(minv, minv, A, K, arr))
 
    # Root's value is changed to 0 and all the nodes are changed to 0 with cost = min(A, B)
    res = min(res, B + helper(0, 0, min(A, B), K, arr))
 
    return res if res != float('inf') else -1
 
# Driver code
if __name__ == "__main__":
    N = 4
    Par = [-1, 0, 1, 2]
    Arr = [65, 2, 80, 4]
    K = 8
    A = 3
    B = 1
 
    # Function call
    print(solve(N, Par, Arr, K, A, B))


Output

2






Time Complexity: O(N), where N is the number of vertices in the graph.
Auxiliary Space: O(1)



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads