Given a 2D array houses[][] consisting of n 2D coordinates [x, y] where each coordinate represents the location of each house, find the minimum cost to connect all the houses of the city.
Note: Cost of connecting two houses is theManhattan Distance between the two points (xi, yi) and (xj, yj) i.e., |xi - xj| + |yi - yj|, where |p| denotes the absolute value of p.
Connect house 1 (0, 7) and house 2 (0, 9) with cost = 2 Connect house 1 (0, 7) and house 3 (20, 7) with cost = 20 Connect house 3 (20, 7) with house 4 (30, 7) with cost = 10Â At last, connect house 4 (30, 7) with house 5 (40, 70) with cost 73. All the houses are connected now. The overall minimum cost is 2 + 10 + 20 + 73 = 105.
Input: houses[][] = [[4, 12], [15, 20], [17, 0]] Output: 41 Explanation: Connect house 1 (4, 12) and house 2 (15, 20) with cost = 19 Connect house 2 (15, 20) and house 3 (17, 0) with cost = 22 All the houses are connected now. The overall minimum cost is 19 + 22 = 41.
Using Prim’s Algorithm - Time O(n2 × log(n)) and Space O(n2)
We can think of each house as a node in a graph, and the Manhattan distance between any two houses as the weight of the edge connecting those two nodes. With this interpretation, the problem of connecting all houses with the minimum total cost becomes equivalent to finding a Minimum Spanning Tree (MST) of a complete graph.
Step by Step implementations:
Start with any house (we start with house 0).
Push all distances from this house to other houses into a min-heap (priority queue).
At every step, pick the house with the smallest connection cost that hasn't been visited.
Add that cost to the total cost and mark the house as visited.
Push distances from this new house to all unvisited houses into the heap.
Repeat until all houses are visited and return the total cost.
C++
//Driver Code Starts#include<iostream>#include<vector>#include<queue>#include<cmath>usingnamespacestd;//Driver Code Ends// Calculates Manhattan Distance between two housesintmanhattanDistance(vector<int>&a,vector<int>&b){returnabs(a[0]-b[0])+abs(a[1]-b[1]);}// Returns the minimum cost to connectintminCost(vector<vector<int>>&houses){intn=houses.size();// Min-heap to store {cost, house_index}priority_queue<pair<int,int>,vector<pair<int,int>>,greater<>>minHeap;// Marks whether a house is already connectedvector<bool>visited(n,false);// Start with the first house (index 0)minHeap.push({0,0});inttotalCost=0;while(!minHeap.empty()){pair<int,int>p=minHeap.top();minHeap.pop();intcost=p.first;intu=p.second;if(visited[u])continue;// Mark the house as connected and add the costvisited[u]=true;totalCost+=cost;// Calculate distance to all unvisited houses and add to heapfor(intv=0;v<n;++v){if(!visited[v]){intdist=manhattanDistance(houses[u],houses[v]);minHeap.push({dist,v});}}}returntotalCost;}//Driver Code Startsintmain(){vector<vector<int>>houses={{0,7},{0,9},{20,7},{30,7},{40,70}};intresult=minCost(houses);cout<<result<<endl;return0;}//Driver Code Ends
Java
//Driver Code Startsimportjava.util.PriorityQueue;importjava.util.Comparator;classGfG{//Driver Code Ends// Calculates Manhattan Distance between two housesstaticintmanhattanDistance(int[]a,int[]b){returnMath.abs(a[0]-b[0])+Math.abs(a[1]-b[1]);}// Returns the minimum cost to connect staticintminCost(int[][]houses){intn=houses.length;// Min-heap to store {cost, houseIndex}PriorityQueue<int[]>minHeap=newPriorityQueue<>(Comparator.comparingInt(a->a[0]));// Marks whether a house is already connectedboolean[]visited=newboolean[n];// Start with the first house (index 0)minHeap.offer(newint[]{0,0});inttotalCost=0;while(!minHeap.isEmpty()){int[]curr=minHeap.poll();intcost=curr[0];intu=curr[1];if(visited[u])continue;// Mark as connected and add the costvisited[u]=true;totalCost+=cost;// Add distances to all unvisited housesfor(intv=0;v<n;v++){if(!visited[v]){intdist=manhattanDistance(houses[u],houses[v]);minHeap.offer(newint[]{dist,v});}}}returntotalCost;}//Driver Code Startspublicstaticvoidmain(String[]args){int[][]houses={{0,7},{0,9},{20,7},{30,7},{40,70}};intresult=minCost(houses);System.out.println(result);}}//Driver Code Ends
Python
#Driver Code Startsimportheapq#Driver Code Ends# Calculates Manhattan Distance between two housesdefmanhattanDistance(a,b):returnabs(a[0]-b[0])+abs(a[1]-b[1])# Returns the minimum cost to connect# all houses using Prim's algorithmdefminCost(houses):n=len(houses)# Min-heap to store {cost, house_index}minHeap=[(0,0)]# Marks whether a house is already connectedvisited=[False]*n# Start with the first house (index 0)totalCost=0whileminHeap:cost,u=heapq.heappop(minHeap)# Skip if already connectedifvisited[u]:continue# Mark the house as connected and add the costvisited[u]=TruetotalCost+=cost# Calculate distance to all # unvisited houses and add to heapforvinrange(n):ifnotvisited[v]:dist=manhattanDistance(houses[u],houses[v])heapq.heappush(minHeap,(dist,v))returntotalCost#Driver Code Startsif__name__=="__main__":houses=[[0,7],[0,9],[20,7],[30,7],[40,70]]result=minCost(houses)print(result)#Driver Code Ends
C#
//Driver Code StartsusingSystem;usingSystem.Collections.Generic;classGfG{//Driver Code Ends// Calculates Manhattan Distance between two housesstaticintmanhattanDistance(int[,]houses,inti,intj){returnMath.Abs(houses[i,0]-houses[j,0])+Math.Abs(houses[i,1]-houses[j,1]);}// Returns the minimum cost to connect// all houses using Prim's algorithmstaticintminCost(int[,]houses){intn=houses.GetLength(0);// Min-heap to store {cost, house_index, tieBreaker}varminHeap=newSortedSet<(intcost,intindex,inttieBreaker)>();inttie=0;minHeap.Add((0,0,tie++));// Marks whether a house is already connectedbool[]visited=newbool[n];inttotalCost=0;while(minHeap.Count>0){varp=minHeap.Min;minHeap.Remove(p);intcost=p.cost;intu=p.index;if(visited[u])continue;// Mark the house as connected and add the costvisited[u]=true;totalCost+=cost;// Calculate distance to all unvisited houses and add to heapfor(intv=0;v<n;++v){if(!visited[v]){intdist=manhattanDistance(houses,u,v);minHeap.Add((dist,v,tie++));}}}returntotalCost;}staticvoidMain(){//Driver Code Startsint[,]houses=newint[,]{{0,7},{0,9},{20,7},{30,7},{40,70}};intresult=minCost(houses);Console.WriteLine(result);}}//Driver Code Ends
JavaScript
// Min-Heap ImplementationclassMinHeap{constructor(){this.heap=[];}push(p){this.heap.push(p);leti=this.heap.length-1;while(i>0){letparent=Math.floor((i-1)/2);if(this.heap[parent][0]<=this.heap[i][0])break;[this.heap[parent],this.heap[i]]=[this.heap[i],this.heap[parent]];i=parent;}}pop(){letp=this.heap[0];letlast=this.heap.pop();if(this.heap.length>0){this.heap[0]=last;leti=0;while(true){letleft=2*i+1;letright=2*i+2;letsmallest=i;if(left<this.heap.length&&this.heap[left][0]<this.heap[smallest][0]){smallest=left;}if(right<this.heap.length&&this.heap[right][0]<this.heap[smallest][0]){smallest=right;}if(smallest===i)break;[this.heap[i],this.heap[smallest]]=[this.heap[smallest],this.heap[i]];i=smallest;}}returnp;}isEmpty(){returnthis.heap.length===0;}}// Calculates Manhattan Distance between two housesfunctionmanhattanDistance(a,b){returnMath.abs(a[0]-b[0])+Math.abs(a[1]-b[1]);}// Returns the minimum cost to connect all houses using Prim's algorithmfunctionminCost(houses){letn=houses.length;// Min-heap to store {cost, house_index}letminHeap=newMinHeap();// Marks whether a house is already connectedletvisited=newArray(n).fill(false);// Start with the first house (index 0)minHeap.push([0,0]);lettotalCost=0;while(!minHeap.isEmpty()){letp=minHeap.pop();letcost=p[0];letu=p[1];if(visited[u])continue;// Mark the house as connected and add the costvisited[u]=true;totalCost+=cost;// Calculate distance to all unvisited houses and add to heapfor(letv=0;v<n;++v){if(!visited[v]){letdist=manhattanDistance(houses[u],houses[v]);minHeap.push([dist,v]);}}}returntotalCost;}//Driver Code Starts// Driver Code consthouses=[[0,7],[0,9],[20,7],[30,7],[40,70]];constresult=minCost(houses);console.log(result);//Driver Code Ends
Output
105
Using Kruskal's Algorithm - Time O(n2 × log(n)) and Space O(n2)
The idea is to treat each house as a node in a complete weighted graph, where the weight between any two houses is given by their Manhattan distance, representing the connection cost. After generating all such edges, we sort them in non-decreasing order and apply Kruskal’s algorithm to build the Minimum Spanning Tree (MST). During this process, a Disjoint Set Union (DSU) structure with path compression and union by rank is used to efficiently track connected components and ensure that no cycles are formed while selecting edges.
C++
//Driver Code Starts#include<iostream>#include<vector>#include<algorithm>#include<cmath>usingnamespacestd;//Driver Code Ends// DSU using path compression + rank by unionclassDSU{vector<int>parent;vector<int>rank;public:DSU(intn){parent.resize(n,-1);rank.resize(n,1);}// Find functionintfind(inti){if(parent[i]==-1)returni;returnparent[i]=find(parent[i]);}// Union functionvoidunite(intx,inty){ints1=find(x);ints2=find(y);if(s1!=s2){if(rank[s1]<rank[s2]){parent[s1]=s2;}elseif(rank[s1]>rank[s2]){parent[s2]=s1;}else{parent[s2]=s1;rank[s1]+=1;}}}};intminCost(vector<vector<int>>&houses){intn=houses.size();// Create edge list with n nodesvector<vector<int>>edgeList;// Add all possible edgesfor(inti=0;i<n;i++){for(intj=i+1;j<n;j++){intcost=abs(houses[i][0]-houses[j][0])+abs(houses[i][1]-houses[j][1]);edgeList.push_back({cost,i,j});}}// Sort all edgessort(edgeList.begin(),edgeList.end());// Initialize the DSUDSUs(n);intans=0,count=0;for(autoedge:edgeList){intw=edge[0];intx=edge[1];inty=edge[2];// Take this edge in MST if it does// not form a cycleif(s.find(x)!=s.find(y)){s.unite(x,y);ans+=w;count++;}if(count==n-1){break;}}returnans;}//Driver Code Startsintmain(){vector<vector<int>>houses={{0,7},{0,9},{20,7},{30,7},{40,70}};cout<<minCost(houses);return0;}//Driver Code Ends
Java
//Driver Code Startsimportjava.util.ArrayList;importjava.util.Arrays;importjava.util.Comparator;importjava.util.List;//Driver Code Ends// DSU using path compression + rank by unionclassDSU{privateint[]parent;privateint[]rank;publicDSU(intn){parent=newint[n];rank=newint[n];Arrays.fill(parent,-1);Arrays.fill(rank,1);}// Find functionpublicintfind(inti){if(parent[i]==-1)returni;returnparent[i]=find(parent[i]);}// Union functionpublicvoidunite(intx,inty){ints1=find(x);ints2=find(y);if(s1!=s2){if(rank[s1]<rank[s2]){parent[s1]=s2;}elseif(rank[s1]>rank[s2]){parent[s2]=s1;}else{parent[s2]=s1;rank[s1]+=1;}}}}classGfG{publicstaticintminCost(int[][]houses){intn=houses.length;// Create edge list with n nodesList<int[]>edgeList=newArrayList<>();// Add all possible edgesfor(inti=0;i<n;i++){for(intj=i+1;j<n;j++){intcost=Math.abs(houses[i][0]-houses[j][0])+Math.abs(houses[i][1]-houses[j][1]);edgeList.add(newint[]{cost,i,j});}}// Sort all edgesedgeList.sort(Comparator.comparingInt(a->a[0]));// Initialize the DSUDSUs=newDSU(n);intans=0,count=0;for(int[]edge:edgeList){intw=edge[0];intx=edge[1];inty=edge[2];// Take this edge in MST if it does// not form a cycleif(s.find(x)!=s.find(y)){s.unite(x,y);ans+=w;count++;}if(count==n-1){break;}}returnans;}//Driver Code Startspublicstaticvoidmain(String[]args){int[][]houses={{0,7},{0,9},{20,7},{30,7},{40,70}};System.out.println(minCost(houses));}}//Driver Code Ends
Python
# Disjoint Set Union (DSU) or Union-Find classclassDSU:def__init__(self,n):# Initialize parent and rank arraysself.parent=[-1]*nself.rank=[1]*n# Find functiondeffind(self,i):ifself.parent[i]==-1:returniself.parent[i]=self.find(self.parent[i])returnself.parent[i]# Union functiondefunite(self,x,y):s1=self.find(x)s2=self.find(y)ifs1!=s2:ifself.rank[s1]<self.rank[s2]:self.parent[s1]=s2elifself.rank[s1]>self.rank[s2]:self.parent[s2]=s1else:self.parent[s2]=s1self.rank[s1]+=1# Function to compute minimum cost to connect all housesdefminCost(houses):n=len(houses)# Create edge list with n nodesedgeList=[]# Add all possible edgesforiinrange(n):forjinrange(i+1,n):cost=abs(houses[i][0]-houses[j][0])+abs(houses[i][1]-houses[j][1])edgeList.append((cost,i,j))# Sort all edgesedgeList.sort()# Initialize the DSUs=DSU(n)ans=0count=0forw,x,yinedgeList:# Take this edge in MST if it does# not form a cycleifs.find(x)!=s.find(y):s.unite(x,y)ans+=wcount+=1ifcount==n-1:breakreturnans#Driver Code Startsif__name__=="__main__":houses=[[0,7],[0,9],[20,7],[30,7],[40,70]]print(minCost(houses))#Driver Code Ends
C#
//Driver Code StartsusingSystem;usingSystem.Collections.Generic;//Driver Code Ends// Disjoint Set Union (Union-Find) with path// compression and union by rankclassDSU{privateint[]parent;privateint[]rank;publicDSU(intn){parent=newint[n];rank=newint[n];for(inti=0;i<n;i++){parent[i]=-1;rank[i]=1;}}// Finds the representative (root) of the set that contains ipublicintfind(inti){if(parent[i]==-1)returni;returnparent[i]=find(parent[i]);}// Unites two sets by rankpublicvoidunite(intx,inty){ints1=find(x);ints2=find(y);if(s1!=s2){if(rank[s1]<rank[s2])parent[s1]=s2;elseif(rank[s1]>rank[s2])parent[s2]=s1;else{parent[s2]=s1;rank[s1]++;}}}}classGfG{// Returns the minimum cost to connect all housesstaticintminCost(int[,]houses){intn=houses.GetLength(0);// Create edge list with n nodesList<int[]>edgeList=newList<int[]>();// Add all possible edgesfor(inti=0;i<n;i++){for(intj=i+1;j<n;j++){intcost=Math.Abs(houses[i,0]-houses[j,0])+Math.Abs(houses[i,1]-houses[j,1]);edgeList.Add(newint[]{cost,i,j});}}// Sort all edgesedgeList.Sort((a,b)=>a[0].CompareTo(b[0]));// Initialize the DSUDSUs=newDSU(n);intans=0,count=0;foreach(varedgeinedgeList){intw=edge[0];intx=edge[1];inty=edge[2];// Take this edge in MST if it does// not form a cycleif(s.find(x)!=s.find(y)){s.unite(x,y);ans+=w;count++;}if(count==n-1){break;}}returnans;}//Driver Code StartsstaticvoidMain(){int[,]houses={{0,7},{0,9},{20,7},{30,7},{40,70}};Console.WriteLine(minCost(houses));}}//Driver Code Ends
JavaScript
classDSU{constructor(n){// -1 means node is its own parentthis.parent=newArray(n).fill(-1);// rank (approx tree height)this.rank=newArray(n).fill(1);}// Find ultimate parent (with path compression)find(i){if(this.parent[i]===-1)returni;returnthis.parent[i]=this.find(this.parent[i]);}// Union two sets by rankunite(x,y){lets1=this.find(x);lets2=this.find(y);if(s1!==s2){if(this.rank[s1]<this.rank[s2]){this.parent[s1]=s2;}elseif(this.rank[s1]>this.rank[s2]){this.parent[s2]=s1;}else{this.parent[s2]=s1;this.rank[s1]++;}}}}// build complete graph using Manhattan distancefunctionminCost(houses){letn=houses.length;// Create edge list with n nodesletedgeList=[];// Create all possible edges (complete graph)for(leti=0;i<n;i++){for(letj=i+1;j<n;j++){letcost=Math.abs(houses[i][0]-houses[j][0])+Math.abs(houses[i][1]-houses[j][1]);edgeList.push([cost,i,j]);}}// Step 1: sort edges by weightedgeList.sort((a,b)=>a[0]-b[0]);letdsu=newDSU(n);// total MST costletans=0;// edges included in MSTletcount=0;// Step 2: pick edges greedilyfor(let[w,x,y]ofedgeList){// include edge if it doesn't form a cycleif(dsu.find(x)!==dsu.find(y)){dsu.unite(x,y);ans+=w;count++;}// MST complete when V-1 edges are addedif(count===n-1)break;}returnans;}//Driver Code Starts// Driver Codelethouses=[[0,7],[0,9],[20,7],[30,7],[40,70]];console.log(minCost(houses));//Driver Code Ends