You are given an array points representing integer coordinates of some points on a 2D-plane, where points[i] = [xi, yi].
The cost of connecting two points [xi, yi] and [xj, yj] is the manhattan distance between them: |xi - xj| + |yi - yj|, where |val| denotes the absolute value of val.
Return the minimum cost to make all points connected. All points are connected if there is exactly one simple path between any two points.
solution
Here, we are essentially trying to find the minimum spanning tree (MST) of the graph.
We use Kruskal’s MST algorithm below, implemented with union find to determine which edges can be skipped in amortized constant time.
- We enumerate all possible edges and costs, and sort them by cost.
- Going through costs from small to large, we connect two points if they are not yet part of the same connected tree.
def minCostConnectPoints(self, points: List[List[int]]) -> int:
n = len(points)
edges = []
point_to_idx = {
(x,y): i
for i, (x, y) in enumerate(points)
}
for i in range(n-1):
for j in range(i+1, n):
x1, y1 = points[i]
x2, y2 = points[j]
cost = abs(x1-x2) + abs(y1-y2)
edges.append((cost, x1, y1, x2, y2))
edges.sort()
# start with disconnected points
parents = [tuple(points[idx]) for idx in range(n)]
# size of tree rooted at point i
sizes = [1]*n
def union(u, v):
pu, pv = find(u), find(v)
# already unioned, skip edge
if pu == pv:
return False
pui, pvi = point_to_idx[pu], point_to_idx[pv]
if sizes[pui] < sizes[pvi]:
pu, pv = pv, pu
pui, pvi = pvi, pui
parents[pvi] = pu
sizes[pui] += sizes[pvi]
return True
def find(u):
ui = point_to_idx[u]
if u != parents[ui]:
parents[ui] = find(parents[ui])
return parents[ui]
ans = 0
for cost, x1, y1, x2, y2 in edges:
if union((x1, y1), (x2, y2)):
ans += cost
return ans