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++
// C++ code for the above approach:#include<bits/stdc++.h>usingnamespacestd;// Parent array to store parent of// each component of DSU.intparent[1001];// sizez array to apply DSU by size.intsizez[1001];// This function is used to initialize// the DSU.voidmake(inti){parent[i]=i;sizez[i]=1;}// This function is used to find the// parent of each component of DSUintfind(intv){if(v==parent[v])returnv;returnparent[v]=find(parent[v]);}// This function is used to merge two// components of DSU.voidUnion(inta,intb){// Finding the parents of vertex// a and ba=find(a);b=find(b);// If parents are not equalif(a!=b){if(sizez[a]<sizez[b])swap(a,b);parent[b]=a;// Apply DSU by sizesizez[a]+=sizez[b];}}// Funtion to solve the problemintminCostToProvideWater(intn,vector<int>&wells,vector<vector<int>>&pipes){// set to store the edges sorted on// the basis of weights.set<vector<int>>st;// Inserting the edges into the setfor(autoe:pipes){intu=e[0];intv=e[1];intwt=e[2];st.insert({wt,u,v});}// Inserting the edges created by the// pseudo vertex i.e. 0for(inti=0;i<n;i++){st.insert({wells[i],0,i+1});}// Initializing the DSUfor(inti=0;i<=n;i++){make(i);}intanswer=0;// Applying Krushkal's MST algorithmwhile(st.size()){autoit=st.begin();intwt=(*it)[0];intu=(*it)[1];intv=(*it)[2];if(find(u)!=find(v)){answer+=wt;Union(u,v);}st.erase(st.begin());}returnanswer;}// Driver Functionintmain(){intN=3;vector<int>wells={1,2,2};vector<vector<int>>pipes={{1,2,1},{2,3,1}};// Function callcout<<minCostToProvideWater(N,wells,pipes);return0;}
Java
// Java program for the above approachimportjava.util.*;publicclassMain{// Parent array to store parent of// each component of DSU.staticint[]parent=newint[1001];// sizez array to apply DSU by size.staticint[]sizez=newint[1001];// This function is used to initialize// the DSU.staticvoidmake(inti){parent[i]=i;sizez[i]=1;}// This function is used to find the// parent of each component of DSUstaticintfind(intv){if(v==parent[v])returnv;returnparent[v]=find(parent[v]);}// This function is used to merge two// components of DSU.staticvoidUnion(inta,intb){// Finding the parents of vertex// a and ba=find(a);b=find(b);// If parents are not equalif(a!=b){if(sizez[a]<sizez[b]){inttemp=a;a=b;b=temp;}parent[b]=a;// Apply DSU by sizesizez[a]+=sizez[b];}}// Function to solve the problemstaticintminCostToProvideWater(intn,List<Integer>wells,List<List<Integer>>pipes){// set to store the edges sorted on// the basis of weights.TreeSet<List<Integer>>st=newTreeSet<>(newComparator<List<Integer>>(){@Overridepublicintcompare(List<Integer>a,List<Integer>b){returna.get(0).compareTo(b.get(0));}});// Inserting the edges into the setfor(List<Integer>e:pipes){intu=e.get(0);intv=e.get(1);intwt=e.get(2);st.add(Arrays.asList(wt,u,v));}// Inserting the edges created by the// pseudo vertex i.e. 0for(inti=0;i<n;i++){st.add(Arrays.asList(wells.get(i),0,i+1));}// Initializing the DSUfor(inti=0;i<=n;i++){make(i);}intanswer=0;// Applying Kruskal's MST algorithmwhile(!st.isEmpty()){List<Integer>it=st.pollFirst();intwt=it.get(0);intu=it.get(1);intv=it.get(2);if(find(u)!=find(v)){answer+=wt;Union(u,v);}}returnanswer;}// Driver Functionpublicstaticvoidmain(String[]args){intN=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));// Function callSystem.out.println(minCostToProvideWater(N,wells,pipes));}}// This code is contributed by Abhinav Mahajan (abhinav_m22).
Python
importheapq# This function is used to initialize the DSU.defmake(i,parent,sizez):parent[i]=isizez[i]=1# This function is used to find the parent of each component of DSUdeffind(v,parent):ifv==parent[v]:returnvparent[v]=find(parent[v],parent)returnparent[v]# This function is used to merge two components of DSUdefunion(a,b,parent,sizez):a=find(a,parent)b=find(b,parent)ifa!=b:ifsizez[a]<sizez[b]:a,b=b,aparent[b]=asizez[a]+=sizez[b]# Function to solve the problemdefmin_cost_to_provide_water(n,wells,pipes):edges=[]# Inserting the edges into the heap sorted by weightsforpipeinpipes:u,v,wt=pipeedges.append((wt,u,v))# Inserting the edges created by the pseudo-vertex i.e., 0foriinrange(n):edges.append((wells[i],0,i+1))# Initializing DSUparent=[0]*(n+1)sizez=[0]*(n+1)foriinrange(n+1):make(i,parent,sizez)answer=0# Applying Kruskal's MST algorithmedges.sort()foredgeinedges:wt,u,v=edgeiffind(u,parent)!=find(v,parent):answer+=wtunion(u,v,parent,sizez)returnanswer# Driver Functionif__name__=="__main__":N=3wells=[1,2,2]pipes=[(1,2,1),(2,3,1)]# Function callprint(min_cost_to_provide_water(N,wells,pipes))
C#
usingSystem;usingSystem.Collections.Generic;classGFG{// Parent array to store parent of // each component of DSU.staticint[]parent=newint[1001];// Size array to apply DSU by size.staticint[]sizez=newint[1001];// This function is used to initialize the DSU.staticvoidMake(inti){parent[i]=i;sizez[i]=1;}// This function is used to find the parent of // each component of DSU.staticintFind(intv){if(v==parent[v])returnv;returnparent[v]=Find(parent[v]);}// This function is used to merge // two components of DSU.staticvoidUnion(inta,intb){// Finding the parents of vertex a and ba=Find(a);b=Find(b);// If parents are not equalif(a!=b){if(sizez[a]<sizez[b])(a,b)=(b,a);parent[b]=a;// Apply DSU by sizesizez[a]+=sizez[b];}}// Function to solve the problemstaticintMinCostToProvideWater(intn,List<int>wells,List<List<int>>pipes){// Using SortedSet to store the // edges sorted on the basis of weights.SortedSet<List<int>>st=newSortedSet<List<int>>(newGeek());// Inserting the edges into the setforeach(vareinpipes){intu=e[0];intv=e[1];intwt=e[2];st.Add(newList<int>(){wt,u,v});}// Inserting the edges created by the pseudo vertex i.e. 0for(inti=0;i<n;i++){st.Add(newList<int>(){wells[i],0,i+1});}// Initializing the DSUfor(inti=0;i<=n;i++){Make(i);}intanswer=0;// Applying Kruskal's MST algorithmwhile(st.Count>0){varit=st.Min;intwt=it[0];intu=it[1];intv=it[2];if(Find(u)!=Find(v)){answer+=wt;Union(u,v);}st.Remove(it);}returnanswer;}// Custom comparer to sort // the edges based on weightspublicclassGeek:IComparer<List<int>>{publicintCompare(List<int>a,List<int>b){returna[0].CompareTo(b[0]);}}// Driver FunctionstaticvoidMain(){intN=3;List<int>wells=newList<int>(){1,2,2};List<List<int>>pipes=newList<List<int>>{newList<int>{1,2,1},newList<int>{2,3,1}};// Function callConsole.WriteLine(MinCostToProvideWater(N,wells,pipes));}}
JavaScript
// JavaScript code for the above approach:// Parent array to store parent of// each component of DSU.letparent=newArray(1001);// sizez array to apply DSU by size.letsizez=newArray(1001);// This function is used to initialize// the DSU.functionmake(i){parent[i]=i;sizez[i]=1;}// This function is used to find the// parent of each component of DSUfunctionfind(v){if(v==parent[v])returnv;returnparent[v]=find(parent[v]);}// This function is used to merge two// components of DSU.functionUnion(a,b){// Finding the parents of vertex// a and ba=find(a);b=find(b);// If parents are not equalif(a!=b){if(sizez[a]<sizez[b])[a,b]=[b,a];parent[b]=a;// Apply DSU by sizesizez[a]+=sizez[b];}}// Funtion to solve the problemfunctionminCostToProvideWater(n,wells,pipes){// set to store the edges sorted on// the basis of weights.letst=newSet();// Inserting the edges into the setfor(leteofpipes){letu=e[0];letv=e[1];letwt=e[2];st.add([wt,u,v]);}// Inserting the edges created by the// pseudo vertex i.e. 0for(leti=0;i<n;i++){st.add([wells[i],0,i+1]);}// Initializing the DSUfor(leti=0;i<=n;i++){make(i);}letanswer=0;// Applying Krushkal's MST algorithmwhile(st.size){letit=st.values().next().value;letwt=it[0];letu=it[1];letv=it[2];if(find(u)!=find(v)){answer+=wt;Union(u,v);}st.delete(it);}returnanswer;}letN=3;letwells=[1,2,2];letpipes=[[1,2,1],[2,3,1]];console.log(minCostToProvideWater(N,wells,pipes));
Output
3
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)