Open In App

Minimum Operations to make value of all vertices of the tree Zero

Given a tree, where each vertex V has a value A[V] stored in it. The task is to find the minimum number of operations required to make the values stored in all vertices of the tree equal to zero.
Each Operation consists of the following 2 steps: 

  1. Select a Subtree such that the subtree include vertex 1.
  2. Increase/Decrease the value of all vertices of the subtree by 1.

Consider the following tree:



Note: The number in the vertex denotes the vertex number and A[V] denotes the value of the vertex as explained above.



For the following Tree we perform the following 3 operations to make the values all the vertices 
equal to zero: 

Note: The vertices in black represent the subtree selected.

We can solve this problem using Dynamic Programming.
Let dp[i][0] denote the number of operations where any subtree rooted at i is selected and the value of all the vertices is increased by 1. 
Similarly, dp[i][1] denotes the number of operations where any subtree rooted at i is selected and the value of all the vertices is decreased by 1. 
For all the leaves we can easily compute dp[i][0] and dp[i][1] if say a leaf node V is such that A[V] = 0 for some leaf node U, i.e dp[i][1] = A[V] and dp[i][0] = 0 
Now if we are in some non leaf node say v, we look at all of its children, if say increase operation is applied Xi times for a child i of V then we need to apply max(Xi for all children i of node v), increase operations for any subtree rooted at v. Similarly we do the same for Decrease operations for the node V.
The answer is the sum of the increase and decrease operations for node 1 since the operations are applied only on subtrees having node 1.

Below is the implementation of the above approach:




// CPP program to find the Minimum Operations
// to modify values of all tree vertices to zero
#include <bits/stdc++.h>
 
using namespace std;
 
// A utility function to add an edge in an
// undirected graph
void addEdge(vector<int> adj[], int u, int v)
{
    adj[u].push_back(v);
    adj[v].push_back(u);
}
 
// A utility function to print the adjacency list
// representation of graph
void printGraph(vector<int> adj[], int V)
{
    for (int v = 0; v < V; ++v) {
        cout << "\n Adjacency list of vertex "
             << v << "\n head ";
        for (auto x : adj[v])
            cout << "-> " << x;
        printf("\n");
    }
}
 
// Utility Function for findMinOperation()
void findMinOperationUtil(int dp[][2], vector<int> adj[],
                          int A[], int src, int parent)
{
    // Base Case for current node
    dp[src][0] = dp[src][1] = 0;
 
    // iterate over the adjacency list for src
    for (auto V : adj[src]) {
        if (V == parent)
            continue;
 
        // calculate DP table for each child V
        findMinOperationUtil(dp, adj, A, V, src);
 
        // Number of Increase Type operations for node src
        // is equal to maximum of number of increase operations
        // required by each of its child
        dp[src][0] = max(dp[src][0], dp[V][0]);
 
        // Number of Decrease Type operations for node src
        // is equal to maximum of number of decrease operations
        // required by each of its child
        dp[src][1] = max(dp[src][1], dp[V][1]);
    }
 
    // After performing operations for subtree rooted at src
    // A[src] changes by the net difference of increase and
    // decrease type operations
    A[src - 1] += dp[src][0] - dp[src][1];
 
    // for negative value of node src
    if (A[src - 1] > 0) {
        dp[src][1] += A[src - 1];
    }
    else {
        dp[src][0] += abs(A[src - 1]);
    }
}
 
// Returns the minimum operations required to make
// value of all vertices equal to zero, uses
// findMinOperationUtil()
int findMinOperation(vector<int> adj[], int A[], int V)
{
 
    // Initialise DP table
    int dp[V + 1][2];
    memset(dp, 0, sizeof dp);
 
    // find dp[1][0] and dp[1][1]
    findMinOperationUtil(dp, adj, A, 1, 0);
 
    int minOperations = dp[1][0] + dp[1][1];
    return minOperations;
}
 
// Driver code
int main()
{
    int V = 5;
 
    // Build the Graph/Tree
    vector<int> adj[V + 1];
    addEdge(adj, 1, 2);
    addEdge(adj, 1, 3);
 
    int A[] = { 1, -1, 1 };
    int minOperations = findMinOperation(adj, A, V);
    cout << minOperations;
 
    return 0;
}




//Java code for the above approach
 
import java.util.*;
 
public class Main {
    // A utility function to add an edge in an
    // undirected graph
    public static void addEdge(List<Integer>[] adj, int u, int v) {
        adj[u].add(v);
        adj[v].add(u);
    }
 
    // A utility function to print the adjacency list
    // representation of graph
    public static void printGraph(List<Integer>[] adj, int V) {
        for (int v = 0; v < V; ++v) {
            System.out.println("\n Adjacency list of vertex " + v + "\n head ");
            for (int x : adj[v]) {
                System.out.print("-> " + x);
            }
            System.out.println();
        }
    }
 
    // Utility Function for findMinOperation()
    public static void findMinOperationUtil(int[][] dp, List<Integer>[] adj, int[] A, int src, int parent) {
        // Base Case for current node
        dp[src][0] = dp[src][1] = 0;
 
        // iterate over the adjacency list for src
        for (int V : adj[src]) {
            if (V == parent) {
                continue;
            }
 
            // calculate DP table for each child V
            findMinOperationUtil(dp, adj, A, V, src);
 
            // Number of Increase Type operations for node src
            // is equal to maximum of number of increase operations
            // required by each of its child
            dp[src][0] = Math.max(dp[src][0], dp[V][0]);
 
            // Number of Decrease Type operations for node src
            // is equal to maximum of number of decrease operations
            // required by each of its child
            dp[src][1] = Math.max(dp[src][1], dp[V][1]);
        }
 
        // After performing operations for subtree rooted at src
        // A[src] changes by the net difference of increase and
        // decrease type operations
        A[src - 1] += dp[src][0] - dp[src][1];
 
        // for negative value of node src
        if (A[src - 1] > 0) {
            dp[src][1] += A[src - 1];
        }
        else {
            dp[src][0] += Math.abs(A[src - 1]);
        }
    }
 
    // Returns the minimum operations required to make
    // value of all vertices equal to zero, uses
    // findMinOperationUtil()
    public static int findMinOperation(List<Integer>[] adj, int[] A, int V) {
        // Initialise DP table
        int[][] dp = new int[V + 1][2];
        for (int[] row : dp) {
            Arrays.fill(row, 0);
        }
 
        // find dp[1][0] and dp[1][1]
        findMinOperationUtil(dp, adj, A, 1, 0);
 
        int minOperations = dp[1][0] + dp[1][1];
           
         return minOperations;
    }
   
   
      public static void main(String[] args) {
        int V = 5;
 
        // Build the Graph/Tree
        List<Integer>[] adj = (List<Integer>[])new List[V + 1];
        for (int i = 0; i <= V; i++) {
            adj[i] = new ArrayList<>();
        }
        addEdge(adj, 1, 2);
        addEdge(adj, 1, 3);
 
        int[] A = { 1, -1, 1 };
        int minOperations = findMinOperation(adj, A, V);
        System.out.println(minOperations);
    }
}
//This code is contributed by Potta Lokesh




# Python3 program to find the Minimum Operations
# to modify values of all tree vertices to zero
 
# A utility function to add an
# edge in an undirected graph
def addEdge(adj, u, v):
 
    adj[u].append(v)
    adj[v].append(u)
 
# A utility function to print the adjacency
# list representation of graph
def printGraph(adj, V):
 
    for v in range(0, V):
        print("Adjacency list of vertex", v)
        print("head", end = " ")
         
        for x in adj[v]:
            print("->", x, end = "")
        print()
 
# Utility Function for findMinOperation()
def findMinOperationUtil(dp, adj, A, src, parent):
 
    # Base Case for current node
    dp[src][0] = dp[src][1] = 0
 
    # Iterate over the adjacency list for src
    for V in adj[src]:
        if V == parent:
            continue
 
        # calculate DP table for each child V
        findMinOperationUtil(dp, adj, A, V, src)
 
        # Number of Increase Type operations for node src
        # is equal to maximum of number of increase operations
        # required by each of its child
        dp[src][0] = max(dp[src][0], dp[V][0])
 
        # Number of Decrease Type operations for node
        # src is equal to maximum of number of decrease
        # operations required by each of its child
        dp[src][1] = max(dp[src][1], dp[V][1])
     
    # After performing operations for subtree rooted
    # at src A[src] changes by the net difference of
    # increase and decrease type operations
    A[src - 1] += dp[src][0] - dp[src][1]
 
    # for negative value of node src
    if A[src - 1] > 0:
        dp[src][1] += A[src - 1]
     
    else:
        dp[src][0] += abs(A[src - 1])
 
# Returns the minimum operations required to
# make value of all vertices equal to zero,
# uses findMinOperationUtil()
def findMinOperation(adj, A, V):
 
    # Initialise DP table
    dp = [[0, 0] for i in range(V + 1)]
 
    # find dp[1][0] and dp[1][1]
    findMinOperationUtil(dp, adj, A, 1, 0)
 
    minOperations = dp[1][0] + dp[1][1]
    return minOperations
 
# Driver code
if __name__ == "__main__":
 
    V = 5
 
    # Build the Graph/Tree
    adj = [[] for i in range(V + 1)]
    addEdge(adj, 1, 2)
    addEdge(adj, 1, 3)
 
    A = [1, -1, 1]
    minOperations = findMinOperation(adj, A, V)
    print(minOperations)
 
# This code is contributed by Rituraj Jain




using System;
using System.Collections.Generic;
 
class Program
{
 
  // A utility function to add an edge in an
  // undirected graph
  static void addEdge(List<int>[] adj, int u, int v)
  {
    adj[u].Add(v);
    adj[v].Add(u);
  }
 
  // Utility Function for FindMinOperation()
  static void FindMinOperationUtil(int[,] dp, List<int>[] adj,
                                   int[] A, int src, int parent)
  {
    // Base Case for current node
    dp[src, 0] = dp[src, 1] = 0;
 
    // iterate over the adjacency list for src
    foreach (int V in adj[src])
    {
      if (V == parent)
      {
        continue;
      }
 
      // calculate DP table for each child V
      FindMinOperationUtil(dp, adj, A, V, src);
 
      // Number of Increase Type operations for node src
      // is equal to maximum of number of increase operations
      // required by each of its child
      dp[src, 0] = Math.Max(dp[src, 0], dp[V, 0]);
 
      // Number of Decrease Type operations for node src
      // is equal to maximum of number of decrease operations
      // required by each of its child
      dp[src, 1] = Math.Max(dp[src, 1], dp[V, 1]);
    }
 
    // After performing operations for subtree rooted at src
    // A[src] changes by the net difference of increase and
    // decrease type operations
    A[src - 1] += dp[src, 0] - dp[src, 1];
 
    // for negative value of node src
    if (A[src - 1] > 0)
    {
      dp[src, 1] += A[src - 1];
    }
    else
    {
      dp[src, 0] += Math.Abs(A[src - 1]);
    }
  }
 
  // Returns the minimum operations required to make
  // value of all vertices equal to zero
  static int FindMinOperation(List<int>[] adj, int[] A, int V)
  {
    // Initialise DP table
    int[,] dp = new int[V + 1, 2];
 
    // find dp[1,0] and dp[1,1]
    FindMinOperationUtil(dp, adj, A, 1, 0);
    int minOperations = dp[1, 0] + dp[1, 1];
    return minOperations;
  }
 
  static void Main(string[] args)
  {
    int V = 5;
    List<int>[] adj = new List<int>[V + 1];
    for (int i = 0; i <= V; i++)
      adj[i] = new List<int>();
 
    addEdge(adj, 1, 2);
    addEdge(adj, 1, 3);
 
    int[] A = { 1, -1, 1 };
    int minOperations = FindMinOperation(adj, A, V);
    Console.WriteLine(minOperations);
  }
}




<script>
 
// JavaScript program to find the Minimum Operations
// to modify values of all tree vertices to zero
 
// A utility function to add an edge in an
// undirected graph
function addEdge(adj, u, v)
{
    adj[u].push(v);
    adj[v].push(u);
}
 
// A utility function to print the adjacency list
// representation of graph
function printGraph(adj, V)
{
    for(var v = 0; v < V; ++v) {
        document.write( "<br> Adjacency list of vertex "
            + v+ "<br> head ");
        for (var x of adj[v])
            document.write("-> "+ x);
        document.write("<br>");
    }
}
 
// Utility Function for findMinOperation()
function findMinOperationUtil(dp, adj, A, src, parent)
{
    // Base Case for current node
    dp[src][0] = dp[src][1] = 0;
 
    // iterate over the adjacency list for src
    for (var V of adj[src]) {
        if (V == parent)
            continue;
 
        // calculate DP table for each child V
        findMinOperationUtil(dp, adj, A, V, src);
 
        // Number of Increase Type operations for node src
        // is equal to maximum of number of increase operations
        // required by each of its child
        dp[src][0] = Math.max(dp[src][0], dp[V][0]);
 
        // Number of Decrease Type operations for node src
        // is equal to maximum of number of decrease operations
        // required by each of its child
        dp[src][1] = Math.max(dp[src][1], dp[V][1]);
    }
 
    // After performing operations for subtree rooted at src
    // A[src] changes by the net difference of increase and
    // decrease type operations
    A[src - 1] += dp[src][0] - dp[src][1];
 
    // for negative value of node src
    if (A[src - 1] > 0) {
        dp[src][1] += A[src - 1];
    }
    else {
        dp[src][0] += Math.abs(A[src - 1]);
    }
}
 
// Returns the minimum operations required to make
// value of all vertices equal to zero, uses
// findMinOperationUtil()
function findMinOperation(adj, A, V)
{
 
    // Initialise DP table
    var dp = Array.from(Array(V+1), ()=>Array(2).fill(0));
 
    // find dp[1][0] and dp[1][1]
    findMinOperationUtil(dp, adj, A, 1, 0);
 
    var minOperations = dp[1][0] + dp[1][1];
    return minOperations;
}
 
// Driver code
 
var V = 5;
 
// Build the Graph/Tree
var adj = Array.from(Array(V+1), ()=>Array());
addEdge(adj, 1, 2);
addEdge(adj, 1, 3);
var A = [1, -1, 1];
var minOperations = findMinOperation(adj, A, V);
document.write( minOperations);
 
</script>

Output
3

Complexity Analysis:


Article Tags :