Open In App

Minimize water to fill all tanks connected by given circuit

Improve
Improve
Like Article
Like
Save
Share
Report

Given N tanks connected like a tree, the connections between them in an array Edge[][], and the capacity of each tank in the array cap[], the task is to find the minimum amount of water required to pour into the given tank such that all the tanks are filled.

Note: When a tank is filled, the remaining amount of water is equally distributed among the other tanks which are connected to it except the one which is the source for this tank. Also, the maximum water available is 1018.

Examples:

Input: N = 4, S = 1, Edges = [[1, 2], [1, 3], [2, 4]], Cap = [1, 1, 1, 1]
Output: 5
Explanation: Initially, 5 unit of water is poured into 
tank 1. 2 unit of it flows to tank 2 and 
2 unit of it flows into tank 3. From 2 
unit of water in tank 2, 1 unit flows into 
tank 4 and 1 unit from tank 3 are wasted.

Example 1

Example 1

Input: N = 3 and S = 2, Edges = [[1, 2], [2, 3]], Cap = [1, 1, 1]
Output: 3

 

Approach: This problem can be solved using Depth First Search based on the following idea:

For any depth, the amount of water that needs to flow in every tank is the same as the maximum requirement for a single tank. If this is followed in bottom-up manner we will get the minimum required water in the source.

Follow the steps mentioned below to implement the idea:

  • Create an adjacency list for the tree using the given edges.
  • Create a visited array to store if a node has been visited or not.
  • Now start depth-first traversal from the given start node.
  • Add capacity of the current node in answer. Add the maximum cost of dfs in adjacent nodes multiplied by all connected nodes except the parent node.

dfs[node] = cap[node] + (number of child except parent node) * max(dfs(child))

  • If dfs(node) is greater than 1018 or dfs(child) is -1 then  return -1.

Below is the implementation of the above approach:

C++




// C++ code to implement the approach
 
#include <bits/stdc++.h>
using namespace std;
 
const long long rmx = 1e18;
 
// Function to implement DFS
long long dfs(int node, int num, int cap[],
              vector<vector<int> >& adj,
              vector<int>& vis,
              int start)
{
    // Mark the current node as visited
    vis[node] = 1;
 
    // Initialize answer as capacity required
    // by this node(tank)
    long long ans = cap[node - 1];
 
    // mx to store the max water required
    // by adjacent node
    long long mx = 0;
 
    // DFS traversal
    for (auto child : adj[node]) {
        if (!vis[child]) {
            long long cdfs
                = dfs(child, num, cap, adj,
                      vis, start);
            if (cdfs == -1) {
                mx = -1;
                break;
            }
            mx = max(mx, cdfs);
        }
    }
    if (mx == -1)
        return -1;
    if (node == start)
        ans += adj[node].size() * mx;
    else
        ans += (adj[node].size() - 1) * mx;
 
    if (ans > rmx)
        return -1;
    return ans;
}
 
// Function to find the minimum amount of water
long long minimum_amount(vector<vector<int> >& Edges,
                         int num, int start, int* cap)
{
 
    // Adjacency list to store graph
    vector<vector<int> > adj(num + 1);
 
    // vis array to mark visited nodes
    vector<int> vis(num + 1);
    for (int i = 0; i < Edges.size(); i++) {
        adj[Edges[i][0]].push_back(Edges[i][1]);
        adj[Edges[i][1]].push_back(Edges[i][0]);
    }
    return dfs(start, num, cap, adj, vis, start);
}
 
// Driver code
int main()
{
    int num = 4, start = 1;
    int cap[] = { 1, 1, 1, 1 };
    vector<vector<int> > Edges
        = { { 1, 2 }, { 1, 3 }, { 2, 4 } };
 
    // Function call
    cout << minimum_amount(Edges, num, start, cap);
 
    return 0;
}


Java




// Java code to implement the approach
import java.util.*;
 
class GFG{
 
static long rmx = (long) 1e18;
 
// Function to implement DFS
static long dfs(int node, int num, int cap[],
        Vector<Integer> [] adj,
        int [] vis,
              int start)
{
    // Mark the current node as visited
    vis[node]=1;
 
    // Initialize answer as capacity required
    // by this node(tank)
    long ans = cap[node - 1];
 
    // mx to store the max water required
    // by adjacent node
    long mx = 0;
 
    // DFS traversal
    for (int child : adj[node]) {
        if (vis[child]!=1) {
            long cdfs
                = dfs(child, num, cap, adj,
                      vis, start);
            if (cdfs == -1) {
                mx = -1;
                break;
            }
            mx = Math.max(mx, cdfs);
        }
    }
    if (mx == -1)
        return -1;
    if (node == start)
        ans += adj[node].size() * mx;
    else
        ans += (adj[node].size() - 1) * mx;
 
    if (ans > rmx)
        return -1;
    return ans;
}
 
// Function to find the minimum amount of water
static long minimum_amount(int[][]  Edges,
                         int num, int start, int []cap)
{
 
    // Adjacency list to store graph
    Vector<Integer> []adj  = new Vector[num + 1];
    for(int i = 0; i < num + 1; i++)
        adj[i] = new Vector<Integer>();
    // vis array to mark visited nodes
    int []vis  = new int[num + 1];
 
    for (int i = 0; i < Edges.length; i++) {
        adj[Edges[i][0]].add(Edges[i][1]);
        adj[Edges[i][1]].add(Edges[i][0]);
    }
    return dfs(start, num, cap, adj, vis, start);
}
 
// Driver code
public static void main(String[] args)
{
    int num = 4, start = 1;
    int cap[] = { 1, 1, 1, 1 };
    int[][] Edges
        = { { 1, 2 }, { 1, 3 }, { 2, 4 } };
 
    // Function call
    System.out.print(minimum_amount(Edges, num, start, cap));
 
}
}
 
// This code contributed by shikhasingrajput


Python3




import math
 
class GFG :
    rmx = int(1.0E18)
     
    # Function to implement DFS
    @staticmethod
    def  dfs( node,  num,  cap,  adj,  vis,  start) :
       
        # Mark the current node as visited
        vis[node] = 1
         
        # Initialize answer as capacity required
        # by this node(tank)
        ans = cap[node - 1]
         
        # mx to store the max water required
        # by adjacent node
        mx = 0
        # DFS traversal
        for child in adj[node] :
            if (vis[child] != 1) :
                cdfs = GFG.dfs(child, num, cap, adj, vis, start)
                if (cdfs == -1) :
                    mx = -1
                    break
                mx = max(mx,cdfs)
        if (mx == -1) :
            return -1
        if (node == start) :
            ans += len(adj[node]) * mx
        else :
            ans += (len(adj[node]) - 1) * mx
        if (ans > GFG.rmx) :
            return -1
        return ans
       
    # Function to find the minimum amount of water
    @staticmethod
    def  minimum_amount( Edges,  num,  start,  cap) :
       
        # Adjacency list to store graph
        adj = [None] * (num + 1)
        i = 0
        while (i < num + 1) :
            adj[i] =  []
            i += 1
             
        # vis array to mark visited nodes
        vis = [0] * (num + 1)
        i = 0
        while (i < len(Edges)) :
            adj[Edges[i][0]].append(Edges[i][1])
            adj[Edges[i][1]].append(Edges[i][0])
            i += 1
        return GFG.dfs(start, num, cap, adj, vis, start)
       
    # Driver code
    @staticmethod
    def main( args) :
        num = 4
        start = 1
        cap = [1, 1, 1, 1]
        Edges = [[1, 2], [1, 3], [2, 4]]
         
        # Function call
        print(GFG.minimum_amount(Edges, num, start, cap))
     
if __name__=="__main__":
    GFG.main([])
     
    # This code is contributed by aaditya burujwale.


C#




// C# code to implement the approach
using System;
using System.Collections.Generic;
 
public class GFG{
 
static long rmx = (long) 1e18;
 
// Function to implement DFS
static long dfs(int node, int num, int []cap,
        List<int> [] adj,
        int [] vis,
              int start)
{
    // Mark the current node as visited
    vis[node]=1;
 
    // Initialize answer as capacity required
    // by this node(tank)
    long ans = cap[node - 1];
 
    // mx to store the max water required
    // by adjacent node
    long mx = 0;
 
    // DFS traversal
    foreach (int child in adj[node]) {
        if (vis[child]!=1) {
            long cdfs
                = dfs(child, num, cap, adj,
                      vis, start);
            if (cdfs == -1) {
                mx = -1;
                break;
            }
            mx = Math.Max(mx, cdfs);
        }
    }
    if (mx == -1)
        return -1;
    if (node == start)
        ans += adj[node].Count * mx;
    else
        ans += (adj[node].Count - 1) * mx;
 
    if (ans > rmx)
        return -1;
    return ans;
}
 
// Function to find the minimum amount of water
static long minimum_amount(int[,]  Edges,
                         int num, int start, int []cap)
{
 
    // Adjacency list to store graph
    List<int> []adj  = new List<int>[num + 1];
    for(int i = 0; i < num + 1; i++)
        adj[i] = new List<int>();
    // vis array to mark visited nodes
    int []vis  = new int[num + 1];
 
    for (int i = 0; i < Edges.GetLength(0); i++) {
        adj[Edges[i,0]].Add(Edges[i,1]);
        adj[Edges[i,1]].Add(Edges[i,0]);
    }
    return dfs(start, num, cap, adj, vis, start);
}
 
// Driver code
public static void Main(String[] args)
{
    int num = 4, start = 1;
    int []cap = { 1, 1, 1, 1 };
    int[,] Edges
        = { { 1, 2 }, { 1, 3 }, { 2, 4 } };
 
    // Function call
    Console.Write(minimum_amount(Edges, num, start, cap));
 
}
}
 
 
// This code contributed by shikhasingrajput


Javascript




// JS code to implement the approach
let rmx = 1e18;
 
// Function to implement DFS
function dfs(node, num, cap, adj, vis, start)
     
{
    // Mark the current node as visited
    vis[node] = 1;
 
    // Initialize answer as capacity required
    // by this node(tank)
    let ans = cap[node - 1];
 
    // mx to store the max water required
    // by adjacent node
    let mx = 0;
 
    // DFS traversal
    for (let child of adj[node]) {
        if (vis[child]!=1) {
            let cdfs
                = dfs(child, num, cap, adj,
                      vis, start);
            if (cdfs == -1) {
                mx = -1;
                break;
            }
            mx = Math.max(mx, cdfs);
        }
    }
    if (mx == -1)
        return -1;
    if (node == start)
        ans += adj[node].length * mx;
    else
        ans += (adj[node].length - 1) * mx;
 
    if (ans > rmx)
        return -1;
    return ans;
}
 
// Function to find the minimum amount of water
function minimum_amount(Edges,  num,   start, cap)
{
 
    // Adjacency list to store graph
    let adj = new Array(num + 1);
    for (var i = 0; i <= num; i++)
        adj[i] = new Array();
    
    // vis array to mark visited nodes
    let vis  = new Array(num + 1);
 
    for (var i = 0; i < Edges.length; i++) {
        adj[Edges[i][0]].push(Edges[i][1]);
        adj[Edges[i][1]].push(Edges[i][0]);
    }
    return dfs(start, num, cap, adj, vis, start);
}
 
// Driver code
let num = 4, start = 1;
let cap = [ 1, 1, 1, 1 ];
let Edges = [[ 1, 2 ], [ 1, 3 ], [2, 4 ]];
 
// Function call
console.log(minimum_amount(Edges, num, start, cap));
 
// This code contributed by phasing17


Output

5

Time Complexity: O(V + E), where V is the number of vertices and E is the number of edges.
Auxiliary Space: O(V)



Last Updated : 08 Nov, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads