Min Cost to Connect All Points

Medium Heaps

Problem

Given an array points where points[i] = [xi, yi] represents a point on the 2D plane, return the minimum cost to make all points connected such that there is exactly one simple path between any two points. The cost of connecting two points is the Manhattan distance between them.

  • 1 ≤ points.length ≤ 1000
  • −10⁶ ≤ xi, yi ≤ 10⁶
  • All points are distinct

Example

Input: points = [[0,0],[2,2],[3,10],[5,2],[7,0]]
Output: 20

The algorithm constructs a minimum spanning tree (MST) connecting all points with minimum total cost. It starts from point 0 with cost 0, adds edges to neighbors with their Manhattan distances, and uses a min-heap to greedily select the next edge with the smallest cost that connects a new point. The MST edges chosen are (0-1), (1-3), (3-4), and (1-2) with costs 4, 3, 5, and 8 respectively, summing to 20.

Approach

Straightforward Solution

A brute-force approach would consider all edges between points (O(N^2)) and run a standard MST algorithm like Kruskal's or Prim's. However, explicitly storing all edges is expensive and unnecessary.

Core Observation

The problem reduces to finding a minimum spanning tree (MST) over a complete graph where vertices are points and edge weights are Manhattan distances. The MST ensures all points are connected with minimum total edge cost.

Path to Optimal

Prim's algorithm can be adapted to this problem by dynamically computing edges from the current MST to unvisited points, using a min-heap to select the next minimal edge. This avoids storing all edges upfront and achieves O(N^2 log N) time by pushing edges lazily. The key insight is that Manhattan distances can be computed on the fly, and the min-heap efficiently picks the next best edge.

Optimal Approach

Build an adjacency list representing the complete graph with Manhattan distances. Use a min-heap initialized with the starting point (cost 0). Repeatedly pop the smallest edge from the heap, skip if the point is visited, otherwise add its cost to the result and push all edges from this point to unvisited neighbors into the heap. Continue until all points are visited. This yields the MST cost efficiently.

Time

O(N^2 log N)

Constructing the adjacency list requires O(N^2) to compute all pairwise Manhattan distances. The main loop runs until all N points are visited, and each edge insertion into the heap costs O(log N). Since each point can push up to O(N) edges, the total complexity is O(N^2 log N).

Space

O(N^2)

The adjacency list stores all edges between points, which is O(N^2). The min-heap can hold up to O(N^2) edges in the worst case. This space is necessary for this approach since the graph is complete.

Pattern Spotlight

Heap / Priority Queue (Prim's Algorithm for MST)

Use a min-heap to greedily select the next minimum cost edge connecting the growing MST to unvisited nodes, dynamically generating edges to avoid storing the entire graph explicitly.

Solution

1import heapq
2
3class Solution:
4 def minCostConnectPoints(self, points: list[list[int]]) -> int:
5 N = len(points)
6 adj = { i:[] for i in range(N) }
7 for i in range(N):
8 x1, y1 = points[i]
9 for j in range(i + 1, N):
10 x2, y2 = points[j]
11 dist = abs(x1 - x2) + abs(y1 - y2)
12 adj[i].append([dist, j])
13 adj[j].append([dist, i])
14
15 res = 0
16 visit = set()
17 min_heap = [[0, 0]]
18 while len(visit) < N:
19 cost, i = heapq.heappop(min_heap)
20 if i in visit:
21 continue
22 res += cost
23 visit.add(i)
24 for nei_cost, nei in adj[i]:
25 if nei not in visit:
26 heapq.heappush(min_heap, [nei_cost, nei])
27 return res

Step-by-Step Solution

1

Construct Complete Graph with Manhattan Distances

5N = len(points)
6adj = { i:[] for i in range(N) }
7for i in range(N):
8 x1, y1 = points[i]
9 for j in range(i + 1, N):
10 x2, y2 = points[j]
11 dist = abs(x1 - x2) + abs(y1 - y2)
12 adj[i].append([dist, j])
13 adj[j].append([dist, i])

Objective

To build an adjacency list representing all edges between points with their Manhattan distances as weights.

Key Insight

The problem models a complete graph where each point connects to every other with an edge weighted by Manhattan distance. Precomputing these distances and storing them in an adjacency list allows efficient access during MST construction. Although this requires O(N^2) time and space, it enables quick edge lookups during the main algorithm.

Interview Quick-Check

Core Logic

Compute Manhattan distance for every pair of points and store bidirectional edges in the adjacency list to represent the complete graph.

Complexity

This step takes O(N^2) time and space, which is acceptable given the problem constraints.

Common Pitfalls & Bugs

Forgetting to add edges in both directions (i to j and j to i) would break the undirected graph assumption.

2

Apply Prim's Algorithm Using a Min-Heap to Build MST

15res = 0
16visit = set()
17min_heap = [[0, 0]]
18while len(visit) < N:
19 cost, i = heapq.heappop(min_heap)
20 if i in visit:
21 continue
22 res += cost
23 visit.add(i)
24 for nei_cost, nei in adj[i]:
25 if nei not in visit:
26 heapq.heappush(min_heap, [nei_cost, nei])
27return res

Objective

To iteratively select the minimum cost edge connecting the MST to an unvisited point, accumulating the total cost.

Key Insight

Prim's algorithm grows the MST by starting from an arbitrary node and repeatedly adding the smallest edge that connects a new point. Using a min-heap to store candidate edges ensures efficient retrieval of the next minimal edge. The visited set prevents cycles by skipping already included points. This approach guarantees the MST with minimal total cost.

Interview Quick-Check

Core Logic

Use a min-heap to always pick the smallest edge connecting the MST to an unvisited point, adding its cost and expanding the MST.

State & Boundaries

Continue until all points are visited, ensuring the MST spans all nodes.

Common Pitfalls & Bugs

Skipping edges leading to already visited points is critical to avoid cycles and incorrect cost accumulation.

Complexity

Heap operations dominate runtime, but the approach remains efficient for up to 1000 points.

Line Analysis

This solution has 3 Critical lines interviewers watch for.

Line 17 Critical
min_heap = [[0, 0]]

Initialize min-heap with starting point 0 and cost 0.

Starting the MST from point 0 with zero cost seeds the algorithm and ensures the heap always has candidate edges.

Line 19 Critical
cost, i = heapq.heappop(min_heap)

Pop the smallest cost edge from the heap.

Selecting the minimal edge ensures the MST grows optimally by always adding the least costly connection.

Line 27 Critical
return res

Return the total cost of the MST after all points are connected.

The accumulated cost represents the minimum cost to connect all points with no cycles, fulfilling the problem requirement.

Line 11 Core
dist = abs(x1 - x2) + abs(y1 - y2)

Calculate Manhattan distance between points i and j.

Manhattan distance defines the edge weight, which is the cost to connect these two points.

Line 16 Core
visit = set()

Create a set to track visited points.

Visited set prevents cycles and ensures each point is added to the MST exactly once.

Line 20 Core
if i in visit:

Skip if the point is already visited.

Avoids cycles and redundant processing by ignoring edges leading to points already in the MST.

Line 22 Core
res += cost

Add the edge cost to the total MST cost.

Accumulates the cost of the newly added edge, progressively building the MST's total cost.

Line 23 Core
visit.add(i)

Mark the current point as visited.

Records that this point is now part of the MST, preventing future cycles and redundant edges.

Line 25 Core
if nei not in visit:

Check if neighbor point is unvisited.

Only unvisited neighbors are candidates for MST expansion, ensuring no cycles are formed.

Line 26 Core
heapq.heappush(min_heap, [nei_cost, nei])

Push neighbor edge into the min-heap for future consideration.

Adds candidate edges to the heap, maintaining the priority queue of minimal edges for MST growth.

Line 6 Core
adj = { i:[] for i in range(N) }

Initialize adjacency list as a dictionary with empty lists for each point.

This data structure will hold all edges for each point, enabling efficient access to neighbors and their edge costs.

Line 12 Core
adj[i].append([dist, j])

Add edge from i to j with computed distance.

Storing this edge in adjacency list allows quick access to neighbors during MST construction.

Line 13 Core
adj[j].append([dist, i])

Add edge from j to i with computed distance to maintain undirected graph.

Ensures the graph is undirected by storing edges in both directions, which is essential for correct MST traversal.

Line 18 Core
while len(visit) < N:

Loop until all points are visited.

Ensures the MST spans all points by continuing until every point is included.

Line 21 Core
continue

Continue to next iteration if point was visited.

This control flow prevents adding duplicate edges and maintains correctness of MST construction.

Line 24 Core
for nei_cost, nei in adj[i]:

Iterate over neighbors of the current point.

Explores all edges from the newly added point to unvisited points, expanding the MST frontier.

Line 7 Standard
for i in range(N):

Iterate over each point index i to build edges.

Outer loop to pair each point with all subsequent points, ensuring all edges are considered once.

Line 9 Standard
for j in range(i + 1, N):

Iterate over each point index j greater than i to avoid duplicate edges.

Inner loop pairs point i with all points after it, ensuring each edge is processed once and stored bidirectionally.

Line 15 Standard
res = 0

Initialize result variable to accumulate total MST cost.

This variable will sum the costs of all edges included in the MST.

Line 5 Basic
N = len(points)

Store the number of points in variable N.

Caching the number of points avoids repeated calls to len(points) and clarifies the problem size for subsequent loops.

Line 8 Basic
x1, y1 = points[i]

Extract x and y coordinates of point i.

Coordinates are needed to compute Manhattan distances to other points.

Line 10 Basic
x2, y2 = points[j]

Extract x and y coordinates of point j.

Coordinates of the second point in the pair are required for distance calculation.

Test Your Understanding

Why does Prim's algorithm guarantee the minimum total cost to connect all points?

Prim's algorithm grows the MST by always choosing the smallest edge connecting the current tree to an unvisited node, ensuring no cycles and minimal incremental cost at each step, which leads to a globally minimum spanning tree.

Related Problems

Heaps pattern

Don't just read it. Drill it.

Reconstruct Min Cost to Connect All Points from memory until it sticks. AlgoDrill blanks out key lines and makes you fill them back in, step by step.

Unlock the Min Cost to Connect All Points drill

or drill a free problem