Given a 2D array houses[][] consisting of N 2D coordinates {x, y} where each coordinate represents the location of each house, the task is to find the minimum cost to connect all the houses of the city.
Cost of connecting two houses is the Manhattan Distance between the two points (xi, yi) and (xj, yj) i.e., |xi – xj| + |yi – yj|, where |p| denotes the absolute value of p.
Examples:
Input: houses[][] = [[0, 0], [2, 2], [3, 10], [5, 2], [7, 0]]
Output: 20
Explanation:

Connect house 1 (0, 0) with house 2 (2, 2) with cost = 4
Connect house 2 (2, 2) with house 3 (3, 10) with cost =9
Connect house 2 (2, 2) with house 4 (5, 2) with cost =3
At last, connect house 4 (5, 2) with house 5 (7, 0) with cost 4.
All the houses are connected now.
The overall minimum cost is 4 + 9 + 3 + 4 = 20.
Input: houses[][] = [[3, 12], [-2, 5], [-4, 1]]
Output: 18
Explanation:
Connect house 1 (3, 12) with house 2 (-2, 5) with cost = 12
Connect house 2 (-2, 5) with house 3 (-4, 1) with cost = 6
All the houses are connected now.
The overall minimum cost is 12 + 6 = 18.
Approach: The idea is to create a weighted graph from the given information with weights between any pair of edges equal to the cost of connecting them, say Ci i.e., the Manhattan distance between the two coordinates. Once the graph is generated, apply Kruskal’s Algorithm to find the Minimum Spanning Tree of the graph using Disjoint Set. Finally, print the minimum cost.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
vector< int > parent, size;
int find_set( int v)
{
if (v == parent[v])
return v;
return parent[v]
= find_set(parent[v]);
}
int union_sets( int a, int b)
{
a = find_set(a);
b = find_set(b);
if (a != b) {
if (size[a] < size[b])
swap(a, b);
parent[b] = a;
size[a] += size[b];
return 1;
}
return 0;
}
void MST( int houses[][2], int n)
{
vector<pair< int , pair< int , int > > > v;
for ( int i = 0; i < n; i++) {
for ( int j = i + 1; j < n; j++) {
int p = abs (houses[i][0]
- houses[j][0]);
p += abs (houses[i][1]
- houses[j][1]);
v.push_back({ p, { i, j } });
}
}
parent.resize(n);
size.resize(n);
sort(v.begin(), v.end());
for ( int i = 0; i < n; i++) {
parent[i] = i, size[i] = 1;
}
int ans = 0;
for ( auto x : v) {
if (union_sets(x.second.first,
x.second.second)) {
ans += x.first;
}
}
cout << ans;
}
int main()
{
int houses[][2] = { { 0, 0 }, { 2, 2 },
{ 3, 10 }, { 5, 2 },
{ 7, 0 }};
int N = sizeof (houses)
/ sizeof (houses[0]);
MST(houses, N);
return 0;
}
|
Java
import java.util.*;
class DSU{
int parent[];
int rank[];
DSU( int n)
{
parent = new int [n];
rank = new int [n];
for ( int i = 0 ; i < n; i++)
{
parent[i] = - 1 ;
rank[i] = 1 ;
}
}
int find_set( int v)
{
if (parent[v] == - 1 )
return v;
return parent[v] = find_set(parent[v]);
}
void union_sets( int a, int b)
{
int p1 = find_set(a);
int p2 = find_set(b);
if (p1 != p2)
{
if (rank[p1] > rank[p2])
{
parent[p2] = p1;
rank[p1] += rank[p2];
}
else
{
parent[p1] = p2;
rank[p2] += rank[p1];
}
}
}
}
class GFG{
static void MST( int houses[][], int n)
{
int ans = 0 ;
ArrayList< int []> edges = new ArrayList<>();
for ( int i = 0 ; i < n; i++)
{
for ( int j = i + 1 ; j < n; j++)
{
int p = Math.abs(houses[i][ 0 ] -
houses[j][ 0 ]);
p += Math.abs(houses[i][ 1 ] -
houses[j][ 1 ]);
edges.add( new int []{ p, i, j });
}
}
Collections.sort(edges, new Comparator< int []>()
{
@Override public int compare( int [] o1, int [] o2)
{
return Integer.compare(o1[ 0 ], o2[ 0 ]);
}
});
DSU d = new DSU(n);
for ( int i = 0 ; i < edges.size(); i++)
{
int from = edges.get(i)[ 1 ];
int to = edges.get(i)[ 2 ];
if (d.find_set(from) != d.find_set(to))
{
d.union_sets(from, to);
ans += edges.get(i)[ 0 ];
}
}
System.out.println(ans);
}
public static void main(String args[])
{
int houses[][] = { { 0 , 0 }, { 2 , 2 },
{ 3 , 10 }, { 5 , 2 },
{ 7 , 0 } };
int n = houses.length;
MST(houses, n);
}
}
|
Python3
parent = [ 0 ] * 100
size = [ 0 ] * 100
def find_set(v):
if (v = = parent[v]):
return v
parent[v] = find_set(parent[v])
return parent[v]
def union_sets(a, b):
a = find_set(a)
b = find_set(b)
if (a ! = b):
if (size[a] < size[b]):
a, b = b, a
parent[b] = a
size[a] + = size[b]
return 1
return 0
def MST(houses, n):
v = []
for i in range (n):
for j in range (i + 1 , n):
p = abs (houses[i][ 0 ] -
houses[j][ 0 ])
p + = abs (houses[i][ 1 ] -
houses[j][ 1 ])
v.append([p, i, j])
v = sorted (v)
for i in range (n):
parent[i] = i
size[i] = 1
ans = 0
for x in v:
if (union_sets(x[ 1 ], x[ 2 ])):
ans + = x[ 0 ]
print (ans)
if __name__ = = '__main__' :
houses = [ [ 0 , 0 ], [ 2 , 2 ],
[ 3 , 10 ], [ 5 , 2 ],
[ 7 , 0 ] ]
N = len (houses)
MST(houses, N)
|
Javascript
<script>
let parent = new Array(100).fill(0)
let size = new Array(100).fill(0)
function find_set(v){
if (v == parent[v])
return v
parent[v] = find_set(parent[v])
return parent[v]
}
function union_sets(a, b){
a = find_set(a)
b = find_set(b)
if (a != b){
if (size[a] < size[b]){
a, b = b, a
}
parent[b] = a
size[a] += size[b]
return 1
}
return 0
}
function MST(houses, n){
let v = []
for (let i=0;i<n;i++){
for (let j=i+1;j<n;j++){
let p = Math.abs(houses[i][0] -
houses[j][0])
p += Math.abs(houses[i][1] -
houses[j][1])
v.push([p, i, j])
}
}
v.sort((a,b)=>a[0]-b[0])
for (let i=0;i<n;i++){
parent[i] = i
size[i] = 1
}
let ans = 0
for (let x of v){
if (union_sets(x[1], x[2]))
ans += x[0]
}
document.write(ans, "</br>" )
}
let houses = [ [ 0, 0 ], [ 2, 2 ], [ 3, 10 ], [ 5, 2 ],[ 7, 0 ] ]
let N = houses.length
MST(houses, N)
</script>
|
C#
using System;
class UnionFind
{
private int [] parent;
private int [] size;
public UnionFind( int n)
{
parent = new int [n];
size = new int [n];
for ( int i = 0; i < n; i++)
{
parent[i] = i;
size[i] = 1;
}
}
public int FindSet( int v)
{
if (v == parent[v])
{
return v;
}
parent[v] = FindSet(parent[v]);
return parent[v];
}
public int UnionSets( int a, int b)
{
a = FindSet(a);
b = FindSet(b);
if (a != b)
{
if (size[a] < size[b])
{
int temp = a;
a = b;
b = temp;
}
parent[b] = a;
size[a] += size[b];
return 1;
}
return 0;
}
}
class Program
{
static void Main( string [] args)
{
int [][] houses = new int [][] {
new int [] { 0, 0 },
new int [] { 2, 2 },
new int [] { 3, 10 },
new int [] { 5, 2 },
new int [] { 7, 0 }
};
int n = houses.Length;
Tuple< int , int , int >[] edges = new Tuple< int , int , int >[(n * (n - 1)) / 2];
int count = 0;
for ( int i = 0; i < n; i++)
{
for ( int j = i + 1; j < n; j++)
{
int p = Math.Abs(houses[i][0] - houses[j][0]) +
Math.Abs(houses[i][1] - houses[j][1]);
edges[count++] = Tuple.Create(p, i, j);
}
}
Array.Sort(edges, (a, b) => a.Item1.CompareTo(b.Item1));
UnionFind uf = new UnionFind(n);
int ans = 0;
foreach ( var edge in edges)
{
if (uf.UnionSets(edge.Item2, edge.Item3) == 1)
{
ans += edge.Item1;
}
}
Console.WriteLine(ans);
}
}
|
Time Complexity: O(N2)
Auxiliary Space: O(N2)