Minimum cost to provide water
Last Updated :
23 Nov, 2023
Given an integer N, where N denotes the number of villages numbered 1 to N, an array wells[] where wells[i] denotes the cost to build a water well in the i‘th city, a 2D array pipes in form of [X Y C] which denotes that the cost to connect village X and Y with water pipes is C. Your task is to provide water to each and every village either by building a well in the village or connecting it to some other village having water. Find the minimum cost to do so.
Examples:
Input: N=3, wells=[1, 2, 2], pipes=[[1 2 1], [2 3 1]]
Output: 3
Explanation: Build well in village1 to provide water with cost=1
connect village2 and village1 with cost =1 , now village1 and village2 have water.
Finally connect village3 with village2 with cost=1 , now all the villages have water with total cost=3.
Input: N=4, wells[1, 1, 1, 1], pipes=[[1 2 100], [2 3 100], [2 4 50]]
Output: 4
Explanation: Clearly its better to construct well at each village rather than building costly roads. Hence total cost=1+1+1+1=4.
We can create a graph with villages as vertices and use pipes array to form edges between these villages, also we need to construct a pseudo vertex that is connected to each and every village ‘i’ with an edges weight of wells[i] , in this way we can take care of cost of building the pipes and wells simultaneously. The MST cost of this graph will give us our answer i.e. the minimum cost to provide water to each village.
Illustration:
Suppose, N=4, wells[1, 2, 1, 2], pipes=[[1 2 1], [1 3 3],[2 3 3], [3 4 1]]
Step 1: We construct the graph with villages as the vertex and use pipes array to form edges as shown in fig-1
fig-1
Step 2: Create a pseudo node (0) and add edges from 0 to all other vertices from 1 to N , assign edge weight as wells[i] , for each ‘i’ 1 to N.
fig-2
Step 3: Find the MST of the above graph and return the MST cost= 1+1+1+1= 4 as the answer.
fig-3
Step-by-step algorithm:
- Firstly initialize the DSU data structure i.e. make(), find(), Union(), and parent array.
- Create a set ‘st’ to store the edges sorted in ascending order on the basis of edge weight.
- Insert the edges in ‘st’ using the pipes array.
- Edges between villages(1 to N) and pseudo vertex(0) have to be inserted with edge weight=wells[i] for each village ‘i’.
- Apply Kruskal’s MST algorithm on the set ‘st‘.
- return the MST cost as the answer.
Below is the implementation of the above algorithm:
C++
#include <bits/stdc++.h>
using namespace std;
int parent[1001];
int sizez[1001];
void make( int i)
{
parent[i] = i;
sizez[i] = 1;
}
int find( int v)
{
if (v == parent[v])
return v;
return parent[v] = find(parent[v]);
}
void Union( int a, int b)
{
a = find(a);
b = find(b);
if (a != b) {
if (sizez[a] < sizez[b])
swap(a, b);
parent[b] = a;
sizez[a] += sizez[b];
}
}
int minCostToProvideWater( int n, vector< int >& wells,
vector<vector< int > >& pipes)
{
set<vector< int > > st;
for ( auto e : pipes) {
int u = e[0];
int v = e[1];
int wt = e[2];
st.insert({ wt, u, v });
}
for ( int i = 0; i < n; i++) {
st.insert({ wells[i], 0, i + 1 });
}
for ( int i = 0; i <= n; i++) {
make(i);
}
int answer = 0;
while (st.size()) {
auto it = st.begin();
int wt = (*it)[0];
int u = (*it)[1];
int v = (*it)[2];
if (find(u) != find(v)) {
answer += wt;
Union(u, v);
}
st.erase(st.begin());
}
return answer;
}
int main()
{
int N = 3;
vector< int > wells = { 1, 2, 2 };
vector<vector< int > > pipes
= { { 1, 2, 1 }, { 2, 3, 1 } };
cout << minCostToProvideWater(N, wells, pipes);
return 0;
}
|
Java
import java.util.*;
public class Main {
static int [] parent = new int [ 1001 ];
static int [] sizez = new int [ 1001 ];
static void make( int i) {
parent[i] = i;
sizez[i] = 1 ;
}
static int find( int v) {
if (v == parent[v])
return v;
return parent[v] = find(parent[v]);
}
static void Union( int a, int b) {
a = find(a);
b = find(b);
if (a != b) {
if (sizez[a] < sizez[b]){
int temp = a;
a = b;
b = temp;
}
parent[b] = a;
sizez[a] += sizez[b];
}
}
static int minCostToProvideWater( int n,
List<Integer> wells,
List<List<Integer>> pipes) {
TreeSet<List<Integer>> st = new TreeSet<>( new Comparator<List<Integer>>() {
@Override
public int compare(List<Integer> a, List<Integer> b) {
return a.get( 0 ).compareTo(b.get( 0 ));
}
});
for (List<Integer> e : pipes) {
int u = e.get( 0 );
int v = e.get( 1 );
int wt = e.get( 2 );
st.add(Arrays.asList(wt, u, v));
}
for ( int i = 0 ; i < n; i++) {
st.add(Arrays.asList(wells.get(i), 0 , i + 1 ));
}
for ( int i = 0 ; i <= n; i++) {
make(i);
}
int answer = 0 ;
while (!st.isEmpty()) {
List<Integer> it = st.pollFirst();
int wt = it.get( 0 );
int u = it.get( 1 );
int v = it.get( 2 );
if (find(u) != find(v)) {
answer += wt;
Union(u, v);
}
}
return answer;
}
public static void main(String[] args) {
int N = 3 ;
List<Integer> wells = Arrays.asList( 1 , 2 , 2 );
List<List<Integer>> pipes = Arrays.asList(
Arrays.asList( 1 , 2 , 1 ),
Arrays.asList( 2 , 3 , 1 )
);
System.out.println(minCostToProvideWater(N, wells, pipes));
}
}
|
Python3
import heapq
def make(i, parent, sizez):
parent[i] = i
sizez[i] = 1
def find(v, parent):
if v = = parent[v]:
return v
parent[v] = find(parent[v], parent)
return parent[v]
def union(a, b, parent, sizez):
a = find(a, parent)
b = find(b, parent)
if a ! = b:
if sizez[a] < sizez[b]:
a, b = b, a
parent[b] = a
sizez[a] + = sizez[b]
def min_cost_to_provide_water(n, wells, pipes):
edges = []
for pipe in pipes:
u, v, wt = pipe
edges.append((wt, u, v))
for i in range (n):
edges.append((wells[i], 0 , i + 1 ))
parent = [ 0 ] * (n + 1 )
sizez = [ 0 ] * (n + 1 )
for i in range (n + 1 ):
make(i, parent, sizez)
answer = 0
edges.sort()
for edge in edges:
wt, u, v = edge
if find(u, parent) ! = find(v, parent):
answer + = wt
union(u, v, parent, sizez)
return answer
if __name__ = = "__main__" :
N = 3
wells = [ 1 , 2 , 2 ]
pipes = [
( 1 , 2 , 1 ),
( 2 , 3 , 1 )
]
print (min_cost_to_provide_water(N, wells, pipes))
|
C#
using System;
using System.Collections.Generic;
class GFG
{
static int [] parent = new int [1001];
static int [] sizez = new int [1001];
static void Make( int i)
{
parent[i] = i;
sizez[i] = 1;
}
static int Find( int v)
{
if (v == parent[v])
return v;
return parent[v] = Find(parent[v]);
}
static void Union( int a, int b)
{
a = Find(a);
b = Find(b);
if (a != b)
{
if (sizez[a] < sizez[b])
(a, b) = (b, a);
parent[b] = a;
sizez[a] += sizez[b];
}
}
static int MinCostToProvideWater( int n, List< int > wells, List<List< int >> pipes)
{
SortedSet<List< int >> st = new SortedSet<List< int >>( new Geek());
foreach ( var e in pipes)
{
int u = e[0];
int v = e[1];
int wt = e[2];
st.Add( new List< int >() { wt, u, v });
}
for ( int i = 0; i < n; i++)
{
st.Add( new List< int >() { wells[i], 0, i + 1 });
}
for ( int i = 0; i <= n; i++)
{
Make(i);
}
int answer = 0;
while (st.Count > 0)
{
var it = st.Min;
int wt = it[0];
int u = it[1];
int v = it[2];
if (Find(u) != Find(v))
{
answer += wt;
Union(u, v);
}
st.Remove(it);
}
return answer;
}
public class Geek : IComparer<List< int >>
{
public int Compare(List< int > a, List< int > b)
{
return a[0].CompareTo(b[0]);
}
}
static void Main()
{
int N = 3;
List< int > wells = new List< int >() { 1, 2, 2 };
List<List< int >> pipes = new List<List< int >> { new List< int > { 1, 2, 1 }, new List< int > { 2, 3, 1 } };
Console.WriteLine(MinCostToProvideWater(N, wells, pipes));
}
}
|
Javascript
let parent = new Array(1001);
let sizez = new Array(1001);
function make(i) {
parent[i] = i;
sizez[i] = 1;
}
function find(v) {
if (v == parent[v])
return v;
return parent[v] = find(parent[v]);
}
function Union(a, b) {
a = find(a);
b = find(b);
if (a != b) {
if (sizez[a] < sizez[b])
[a, b] = [b, a];
parent[b] = a;
sizez[a] += sizez[b];
}
}
function minCostToProvideWater(n, wells, pipes) {
let st = new Set();
for (let e of pipes) {
let u = e[0];
let v = e[1];
let wt = e[2];
st.add([wt, u, v]);
}
for (let i = 0; i < n; i++) {
st.add([wells[i], 0, i + 1]);
}
for (let i = 0; i <= n; i++) {
make(i);
}
let answer = 0;
while (st.size) {
let it = st.values().next().value;
let wt = it[0];
let u = it[1];
let v = it[2];
if (find(u) != find(v)) {
answer += wt;
Union(u, v);
}
st. delete (it);
}
return answer;
}
let N = 3;
let wells = [1, 2, 2];
let pipes = [[1, 2, 1], [2, 3, 1]];
console.log(minCostToProvideWater(N, wells, pipes));
|
Time Complexity: O(E*log(N)), where E is the number of edges and N is the number of vertices in the formed graph.
Auxiliary Space: O(N)
Share your thoughts in the comments
Please Login to comment...