Minimum cost to connect all houses in a city

Last Updated : 28 Mar, 2026

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 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, 7], [0, 9], [20, 7], [30, 7], [40, 70]]
Output: 105
Explanation:

11

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.

Try It Yourself
redirect icon

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>
using namespace std;

//Driver Code Ends

// Calculates Manhattan Distance between two houses
int manhattanDistance(vector<int>& a, vector<int>& b) {
    return abs(a[0] - b[0]) + abs(a[1] - b[1]);
}

// Returns the minimum cost to connect
int minCost(vector<vector<int>>& houses) {
    
    int n = 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 connected
    vector<bool> visited(n, false);

    // Start with the first house (index 0)
    minHeap.push({0, 0});

    int totalCost = 0;

    while (!minHeap.empty()) {
        pair<int, int> p = minHeap.top(); minHeap.pop();
        int cost = p.first;
        int u = p.second;

        if (visited[u]) continue;

        // Mark the house as connected and add the cost
        visited[u] = true;
        totalCost += cost;

        // Calculate distance to all unvisited houses and add to heap
        for (int v = 0; v < n; ++v) {
            if (!visited[v]) {
                int dist = manhattanDistance(houses[u], houses[v]);
                minHeap.push({dist, v});
            }
        }
    }

    return totalCost;
}

//Driver Code Starts

int main() {
    
    vector<vector<int>> houses = {
        {0, 7}, {0, 9}, {20, 7}, {30, 7}, {40, 70}
    };
    
    int result = minCost(houses);

    cout << result << endl;

    return 0;
}

//Driver Code Ends
Java
//Driver Code Starts
import java.util.PriorityQueue;
import java.util.Comparator;

 class GfG {

//Driver Code Ends

    // Calculates Manhattan Distance between two houses
    static int manhattanDistance(int[] a, int[] b) {
        return Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]);
    }

    // Returns the minimum cost to connect 
    static int minCost(int[][] houses) {
        int n = houses.length;

        // Min-heap to store {cost, houseIndex}
        PriorityQueue<int[]> minHeap = 
        new PriorityQueue<>(Comparator.comparingInt(a -> a[0]));

        // Marks whether a house is already connected
        boolean[] visited = new boolean[n];

        // Start with the first house (index 0)
        minHeap.offer(new int[]{0, 0});

        int totalCost = 0;

        while (!minHeap.isEmpty()) {
            int[] curr = minHeap.poll();
            int cost = curr[0];
            int u = curr[1];

            if (visited[u]) continue;

            // Mark as connected and add the cost
            visited[u] = true;
            totalCost += cost;

            // Add distances to all unvisited houses
            for (int v = 0; v < n; v++) {
                if (!visited[v]) {
                    int dist = manhattanDistance(houses[u], houses[v]);
                    minHeap.offer(new int[]{dist, v});
                }
            }
        }

        return totalCost;
    }

//Driver Code Starts

    public static void main(String[] args) {
        int[][] houses = {
            {0, 7}, {0, 9}, {20, 7}, {30, 7}, {40, 70}
        };

        int result = minCost(houses);
        System.out.println(result);
    }
}

//Driver Code Ends
Python
#Driver Code Starts
import heapq

#Driver Code Ends

# Calculates Manhattan Distance between two houses
def manhattanDistance(a, b):
    return abs(a[0] - b[0]) + abs(a[1] - b[1])

# Returns the minimum cost to connect
# all houses using Prim's algorithm
def minCost(houses):
    n = len(houses)
    
    # Min-heap to store {cost, house_index}
    minHeap = [(0, 0)]

    # Marks whether a house is already connected
    visited = [False] * n

    # Start with the first house (index 0)
    totalCost = 0

    while minHeap:
        cost, u = heapq.heappop(minHeap)

        # Skip if already connected
        if visited[u]:
            continue

        # Mark the house as connected and add the cost
        visited[u] = True
        totalCost += cost

        # Calculate distance to all 
        # unvisited houses and add to heap
        for v in range(n):
            if not visited[v]:
                dist = manhattanDistance(houses[u], houses[v])
                heapq.heappush(minHeap, (dist, v))

    return totalCost

#Driver Code Starts
    
if __name__ == "__main__":
    houses = [
        [0, 7], [0, 9], [20, 7], [30, 7], [40, 70]
    ]
    result = minCost(houses)
    print(result)

#Driver Code Ends
C#
//Driver Code Starts
using System;
using System.Collections.Generic;

class GfG {
    
//Driver Code Ends

    // Calculates Manhattan Distance between two houses
    static int manhattanDistance(int[,] houses, int i, int j) {
        return Math.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 algorithm
    static int minCost(int[,] houses) {
        int n = houses.GetLength(0);

        // Min-heap to store {cost, house_index, tieBreaker}
        var minHeap = new SortedSet<(int cost, int index, int tieBreaker)>();
        int tie = 0;
        minHeap.Add((0, 0, tie++));

        // Marks whether a house is already connected
        bool[] visited = new bool[n];

        int totalCost = 0;

        while (minHeap.Count > 0) {
            var p = minHeap.Min;
            minHeap.Remove(p);
            int cost = p.cost;
            int u = p.index;

            if (visited[u]) continue;

            // Mark the house as connected and add the cost
            visited[u] = true;
            totalCost += cost;

            // Calculate distance to all unvisited houses and add to heap
            for (int v = 0; v < n; ++v) {
                if (!visited[v]) {
                    int dist = manhattanDistance(houses, u, v);
                    minHeap.Add((dist, v, tie++));
                }
            }
        }

        return totalCost;
    }

    static void Main() {

//Driver Code Starts
        int[,] houses = new int[,]
        { {0, 7}, {0, 9}, {20, 7},{30, 7},{40, 70}
        };

        int result = minCost(houses);
        Console.WriteLine(result);
    }
}

//Driver Code Ends
JavaScript
// Min-Heap Implementation
class MinHeap {
    constructor() {
        this.heap = [];
    }

    push(p) {
        this.heap.push(p);
        let i = this.heap.length - 1;

        while (i > 0) {
            let parent = 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() {
        let p = this.heap[0];
        let last = this.heap.pop();

        if (this.heap.length > 0) {
            this.heap[0] = last;
            let i = 0;

            while (true) {
                let left = 2 * i + 1;
                let right = 2 * i + 2;
                let smallest = 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;
            }
        }

        return p;
    }

    isEmpty() {
        return this.heap.length === 0;
    }
}

// Calculates Manhattan Distance between two houses
function manhattanDistance(a, b) {
    return Math.abs(a[0] - b[0]) + Math.abs(a[1] - b[1]);
}

// Returns the minimum cost to connect all houses using Prim's algorithm
function minCost(houses) {

    let n = houses.length;

    // Min-heap to store {cost, house_index}
    let minHeap = new MinHeap();

    // Marks whether a house is already connected
    let visited = new Array(n).fill(false);

    // Start with the first house (index 0)
    minHeap.push([0, 0]);

    let totalCost = 0;

    while (!minHeap.isEmpty()) {
        let p = minHeap.pop();
        let cost = p[0];
        let u = p[1];

        if (visited[u]) continue;

        // Mark the house as connected and add the cost
        visited[u] = true;
        totalCost += cost;

        // Calculate distance to all unvisited houses and add to heap
        for (let v = 0; v < n; ++v) {
            if (!visited[v]) {
                let dist = manhattanDistance(houses[u], houses[v]);
                minHeap.push([dist, v]);
            }
        }
    }

    return totalCost;
}


//Driver Code Starts
// Driver Code 
const houses = [[0, 7], [0, 9], [20, 7], [30, 7], [40, 70]];

const result = 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>
using namespace std;

//Driver Code Ends

// DSU using path compression + rank by union
class DSU {
    vector<int> parent;
    vector<int> rank;

  public:
    DSU(int n) {
        parent.resize(n, -1);
        rank.resize(n, 1);
    }

    // Find function
    int find(int i) {
        if (parent[i] == -1)
            return i;
        return parent[i] = find(parent[i]);
    }

    // Union function
    void unite(int x, int y) {
        int s1 = find(x);
        int s2 = find(y);

        if (s1 != s2) {
            if (rank[s1] < rank[s2]) {
                parent[s1] = s2;
            }
            else if (rank[s1] > rank[s2]) {
                parent[s2] = s1;
            }
            else {
                parent[s2] = s1;
                rank[s1] += 1;
            }
        }
    }
};

int minCost(vector<vector<int>> &houses) {
    int n = houses.size();

    // Create edge list with n nodes
    vector<vector<int>> edgeList;

    // Add all possible edges
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            int cost = abs(houses[i][0] - houses[j][0]) + 
                       abs(houses[i][1] - houses[j][1]);
            edgeList.push_back({cost, i, j});
        }
    }

    // Sort all edges
    sort(edgeList.begin(), edgeList.end());

    // Initialize the DSU
    DSU s(n);

    int ans = 0, count = 0;

    for (auto edge : edgeList) {
        int w = edge[0];
        int x = edge[1];
        int y = edge[2];

        // Take this edge in MST if it does
        // not form a cycle
        if (s.find(x) != s.find(y)) {
            s.unite(x, y);
            ans += w;
            count++;
        }

        if (count == n - 1) {
            break;
        }
    }

    return ans;
}

//Driver Code Starts

int main() {
    vector<vector<int>> houses = {{0, 7}, {0, 9}, {20, 7}, {30, 7},
                                 {40, 70}};
    cout << minCost(houses);
    return 0;
}
//Driver Code Ends
Java
//Driver Code Starts
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

//Driver Code Ends

// DSU using path compression + rank by union
class DSU {
    private int[] parent;
    private int[] rank;

    public DSU(int n) {
        parent = new int[n];
        rank = new int[n];
        Arrays.fill(parent, -1);
        Arrays.fill(rank, 1);
    }

    // Find function
    public int find(int i) {
        if (parent[i] == -1)
            return i;
        return parent[i] = find(parent[i]);
    }

    // Union function
    public void unite(int x, int y) {
        int s1 = find(x);
        int s2 = find(y);

        if (s1 != s2) {
            if (rank[s1] < rank[s2]) {
                parent[s1] = s2;
            } else if (rank[s1] > rank[s2]) {
                parent[s2] = s1;
            } else {
                parent[s2] = s1;
                rank[s1] += 1;
            }
        }
    }
}

class GfG {
    public static int minCost(int[][] houses) {
        int n = houses.length;

        // Create edge list with n nodes
        List<int[]> edgeList = new ArrayList<>();

        // Add all possible edges
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                int cost = Math.abs(houses[i][0] - houses[j][0]) +
                           Math.abs(houses[i][1] - houses[j][1]);
                edgeList.add(new int[]{cost, i, j});
            }
        }

        // Sort all edges
        edgeList.sort(Comparator.comparingInt(a -> a[0]));

        // Initialize the DSU
        DSU s = new DSU(n);

        int ans = 0, count = 0;

        for (int[] edge : edgeList) {
            int w = edge[0];
            int x = edge[1];
            int y = edge[2];

            // Take this edge in MST if it does
            // not form a cycle
            if (s.find(x) != s.find(y)) {
                s.unite(x, y);
                ans += w;
                count++;
            }

            if (count == n - 1) {
                break;
            }
        }

        return ans;
    }

//Driver Code Starts

    public static void main(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 class
class DSU:
    def __init__(self, n):
        # Initialize parent and rank arrays
        self.parent = [-1] * n
        self.rank = [1] * n

    # Find function
    def find(self, i):
        if self.parent[i] == -1:
            return i
        self.parent[i] = self.find(self.parent[i])
        return self.parent[i]

    # Union function
    def unite(self, x, y):
        s1 = self.find(x)
        s2 = self.find(y)

        if s1 != s2:
            if self.rank[s1] < self.rank[s2]:
                self.parent[s1] = s2
            elif self.rank[s1] > self.rank[s2]:
                self.parent[s2] = s1
            else:
                self.parent[s2] = s1
                self.rank[s1] += 1

# Function to compute minimum cost to connect all houses
def minCost(houses):
    n = len(houses)

    # Create edge list with n nodes
    edgeList = []

    # Add all possible edges
    for i in range(n):
        for j in range(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 edges
    edgeList.sort()

    # Initialize the DSU
    s = DSU(n)

    ans = 0
    count = 0

    for w, x, y in edgeList:

        # Take this edge in MST if it does
        # not form a cycle
        if s.find(x) != s.find(y):
            s.unite(x, y)
            ans += w
            count += 1

        if count == n - 1:
            break

    return ans


#Driver Code Starts
if __name__ == "__main__":
    houses = [[0, 7], [0, 9], [20, 7], [30, 7], [40, 70]]
    print(minCost(houses))
#Driver Code Ends
C#
//Driver Code Starts
using System;
using System.Collections.Generic;

//Driver Code Ends

// Disjoint Set Union (Union-Find) with path
// compression and union by rank
class DSU {
    private int[] parent;
    private int[] rank;

    public DSU(int n) {
        parent = new int[n];
        rank = new int[n];
        for (int i = 0; i < n; i++) {
            parent[i] = -1;
            rank[i] = 1;
        }
    }

    // Finds the representative (root) of the set that contains i
    public int find(int i) {
        if (parent[i] == -1)
            return i;
        return parent[i] = find(parent[i]); 
    }

    // Unites two sets by rank
    public void unite(int x, int y) {
        int s1 = find(x);
        int s2 = find(y);

        if (s1 != s2) {
            if (rank[s1] < rank[s2])
                parent[s1] = s2;
            else if (rank[s1] > rank[s2])
                parent[s2] = s1;
            else {
                parent[s2] = s1;
                rank[s1]++;
            }
        }
    }
}

class GfG {

    // Returns the minimum cost to connect all houses
    static int minCost(int[,] houses) {
        int n = houses.GetLength(0);

        // Create edge list with n nodes
        List<int[]> edgeList = new List<int[]>();

        // Add all possible edges
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                int cost = Math.Abs(houses[i, 0] - houses[j, 0]) +
                           Math.Abs(houses[i, 1] - houses[j, 1]);
                edgeList.Add(new int[] { cost, i, j });
            }
        }

        // Sort all edges
        edgeList.Sort((a, b) => a[0].CompareTo(b[0]));

        // Initialize the DSU
        DSU s = new DSU(n);

        int ans = 0, count = 0;

        foreach (var edge in edgeList) {
            int w = edge[0];
            int x = edge[1];
            int y = edge[2];

            // Take this edge in MST if it does
            // not form a cycle
            if (s.find(x) != s.find(y)) {
                s.unite(x, y);
                ans += w;
                count++;
            }

            if (count == n - 1) {
                break;
            }
        }

        return ans;
    }

//Driver Code Starts

    static void Main() {
        int[,] houses = {
            { 0, 7 },
            { 0, 9 },
            { 20, 7 },
            { 30, 7 },
            { 40, 70 }
        };

        Console.WriteLine(minCost(houses));
    }
}
//Driver Code Ends
JavaScript
class DSU {
    constructor(n) {
        
        // -1 means node is its own parent
        this.parent = new Array(n).fill(-1);
        
        // rank (approx tree height)
        this.rank = new Array(n).fill(1); 
    }

    // Find ultimate parent (with path compression)
    find(i) {
        if (this.parent[i] === -1) return i;
        return this.parent[i] = this.find(this.parent[i]); 
    }

    // Union two sets by rank
    unite(x, y) {
        let s1 = this.find(x);
        let s2 = this.find(y);

        if (s1 !== s2) {
            if (this.rank[s1] < this.rank[s2]) {
                this.parent[s1] = s2;
            } else if (this.rank[s1] > this.rank[s2]) {
                this.parent[s2] = s1;
            } else {
                this.parent[s2] = s1;
                this.rank[s1]++;
            }
        }
    }
}

// build complete graph using Manhattan distance
function minCost(houses) {
    let n = houses.length;

    // Create edge list with n nodes
    let edgeList = [];

    // Create all possible edges (complete graph)
    for (let i = 0; i < n; i++) {
        for (let j = i + 1; j < n; j++) {
            let cost =
                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 weight
    edgeList.sort((a, b) => a[0] - b[0]);

    let dsu = new DSU(n);
    
    // total MST cost
    let ans = 0;  
    
    // edges included in MST
    let count = 0; 

    // Step 2: pick edges greedily
    for (let [w, x, y] of edgeList) {
        
        // include edge if it doesn't form a cycle
        if (dsu.find(x) !== dsu.find(y)) {
            dsu.unite(x, y);
            ans += w;
            count++;
        }

        // MST complete when V-1 edges are added
        if (count === n - 1) break;
    }

    return ans;
}


//Driver Code Starts
// Driver Code
let houses = [[0, 7], [0, 9], [20, 7], [30, 7], [40, 70]];
console.log(minCost(houses));
//Driver Code Ends

Output
105
Comment