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.
 
Example 1:

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

We can connect the points as shown above to get the minimum cost of 20.
Notice that there is a unique path between every pair of points.

Example 2:
Input: points = [[3,12],[-2,5],[-4,1]]
Output: 18

Example 3:
Input: points = [[0,0],[1,1],[1,0],[-1,1]]
Output: 4

Example 4:
Input: points = [[-1000000,-1000000],[1000000,1000000]]
Output: 4000000

Example 5:
Input: points = [[0,0]]
Output: 0

 
Constraints:

1 <= points.length <= 1000
-106 <= xi, yi <= 106
All pairs (xi, yi) are distinct.

Source: leetcode | Difficulty: MEDIUM
Tags: Spanning trees

Graph algorithms

Data structures

Starter code: class Solution:
    def minCostConnectPoints(self, points: List[List[int]]) -> int:
        

Solutions:
class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		score = [-1] * len(points)
		total_score = 0
		for i in range(1, len(points)):
			(x, y) = (points[i - 1][0], points[i - 1][1])
			(cur_min_idx, cur_min_val) = (-1, -1)
			for j in range(i, len(points)):
				cur_dist = abs(x - points[j][0]) + abs(y - points[j][1])
				if score[j] == -1:
					score[j] = cur_dist
				elif cur_dist < score[j]:
					score[j] = cur_dist
				if cur_min_val == -1 or score[j] < cur_min_val:
					(cur_min_val, cur_min_idx) = (score[j], j)
			total_score += cur_min_val
			if i != j:
				(score[cur_min_idx], score[i]) = (score[i], score[cur_min_idx])
				(points[cur_min_idx], points[i]) = (points[i], points[cur_min_idx])
		return total_score


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		cost = 0
		Left_over_points_minEdge = [(abs(points[i][0] - points[0][0]) + abs(points[i][1] - points[0][1]), 0, i) for i in range(1, len(points))]
		heapq.heapify(Left_over_points_minEdge)
		while Left_over_points_minEdge:
			(shortest, frm, to) = heapq.heappop(Left_over_points_minEdge)
			cost += shortest
			for (pos, (d, _, i)) in enumerate(Left_over_points_minEdge):
				dist = abs(points[i][0] - points[to][0]) + abs(points[i][1] - points[to][1])
				if dist < d:
					Left_over_points_minEdge[pos] = (dist, to, i)
					heapq._siftdown(Left_over_points_minEdge, 0, pos)
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def manhattan(x, y):
			return abs(x[0] - y[0]) + abs(x[1] - y[1])
		(ans, n) = (0, len(points))
		seen = set()
		edges = [(0, 0, 0)]
		while len(seen) < n:
			(w, u, v) = heapq.heappop(edges)
			if v in seen:
				continue
			seen.add(v)
			ans += w
			for i in range(len(points)):
				if i not in seen and i != u:
					heapq.heappush(edges, (manhattan(points[v], points[i]), v, i))
		return ans


class DisjointSet:

	def __init__(self, n):
		self.parent = [-1] * n

	def find(self, x):
		if self.parent[x] < 0:
			return x
		else:
			root = self.find(self.parent[x])
			self.parent[x] = root
			return root

	def union(self, a, b):
		root_a = self.find(a)
		root_b = self.find(b)
		if root_a == root_b:
			return False
		if self.parent[root_a] > self.parent[root_b]:
			temp = root_a
			root_a = root_b
			root_b = temp
		self.parent[root_a] += self.parent[root_b]
		self.parent[root_b] = root_a
		return True

	def size(self, x):
		root = self.find(x)
		return self.parent[root] * -1

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []
		for (i, point1) in enumerate(points):
			for j in range(i + 1, len(points)):
				point2 = points[j]
				cost = abs(point2[0] - point1[0]) + abs(point2[1] - point1[1])
				edges.append([cost, i, j])
		ans = 0
		edges.sort()
		graph = DisjointSet(len(points))
		for edge in edges:
			if graph.union(edge[1], edge[2]):
				ans += edge[0]
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		parent = [i for i in range(len(points))]
		size = [1 for _ in range(len(points))]

		def root(p):
			while parent[p] != p:
				parent[p] = parent[parent[p]]
				p = parent[p]
			return p

		def union(p, q):
			(root_p, root_q) = (root(p), root(q))
			if root_p != root_q:
				if size[root_p] < size[root_q]:
					parent[root_p] = root_q
					size[root_q] += size[root_p]
				else:
					parent[root_q] = root_p
					size[root_p] += size[root_q]

		def connected(p, q):
			return root(p) == root(q)
		p = points
		ans = 0

		def dist(p1, p2):
			return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		d = [[(0, _)] * len(p) for _ in range(len(p))]
		heap = []
		for i in range(len(p)):
			for j in range(i + 1, len(p)):
				temp = dist(p[i], p[j])
				d[i][j] = (temp, j)
				d[j][i] = (temp, i)
				heappush(heap, (temp, (i, j)))
		while heap:
			(dis, (i, j)) = heappop(heap)
			if not connected(i, j):
				ans += dis
				union(i, j)
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		to_visit = set(range(1, len(points)))
		pq = [(abs(points[0][0] - points[x][0]) + abs(points[0][1] - points[x][1]), x) for x in range(1, len(points))]
		heapq.heapify(pq)
		ans = 0
		while pq:
			(cost, to) = heapq.heappop(pq)
			if to in to_visit:
				to_visit.remove(to)
				ans += cost
				for nei in to_visit:
					(x, y) = points[nei]
					heapq.heappush(pq, (abs(x - points[to][0]) + abs(y - points[to][1]), nei))
		return ans


import queue
import sys

class Solution:

	def minCostConnectPoints(self, p: List[List[int]]) -> int:
		n = len(p)
		graph = [[] for i in range(n + 1)]
		dist = [1000000000 for i in range(n + 1)]
		for i in range(len(p)):
			for j in range(len(p)):
				if i == j:
					continue
				graph[i].append((j, abs(p[i][0] - p[j][0]) + abs(p[i][1] - p[j][1])))
				graph[j].append((i, abs(p[i][0] - p[j][0]) + abs(p[i][1] - p[j][1])))
		pq = queue.PriorityQueue()
		pq.put((0, 0))
		dist[0] = 0
		res = 0
		while pq.empty() == False:
			(du, u) = pq.get()
			if du != dist[u]:
				continue
			dist[u] = 0
			res += du
			for (v, uv) in graph[u]:
				if dist[v] > uv:
					dist[v] = uv
					pq.put((uv, v))
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def build_graph(points):
			g = {i: {} for i in range(len(points))}
			for i in range(len(points)):
				for j in range(i + 1, len(points)):
					dist = abs(points[j][0] - points[i][0]) + abs(points[j][1] - points[i][1])
					g[i][j] = dist
					g[j][i] = dist
			return g

		def min_span_tree(g):
			import heapq
			cost = 0
			min_heap = []
			heapq.heappush(min_heap, (0, 0))
			visited = set()
			while len(min_heap):
				(nxt_cost, idx) = heapq.heappop(min_heap)
				if idx in visited:
					continue
				visited.add(idx)
				cost += nxt_cost
				for adj in g[idx]:
					if adj not in visited:
						heapq.heappush(min_heap, (g[idx][adj], adj))
			return cost
		g = build_graph(points)
		return min_span_tree(g)


class DSU:

	def __init__(self, N):
		self.par = list(range(N))
		self.sz = [1] * N

	def find(self, x):
		if self.par[x] != x:
			self.par[x] = self.find(self.par[x])
		return self.par[x]

	def union(self, x, y):
		(xr, yr) = (self.find(x), self.find(y))
		if xr == yr:
			return False
		if self.sz[xr] < self.sz[yr]:
			(xr, yr) = (yr, xr)
		self.par[yr] = xr
		self.sz[xr] += self.sz[yr]
		return True

	def size(self, x):
		return self.sz[self.find(x)]

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []
		N = len(points)
		for i in range(N):
			for j in range(i + 1, N):
				d = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				edges.append([d, i, j])
		edges.sort()
		u = DSU(N)
		res = 0
		for edge in edges:
			if u.union(edge[1], edge[2]):
				res += edge[0]
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		dist = collections.defaultdict(dict)
		n = len(points)
		for i in range(n):
			for j in range(i + 1, n):
				d = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				dist[i][j] = dist[j][i] = d
		ret = 0
		visited = set([])
		pq = [(0, 0)]
		while pq:
			(cnt, ind) = heapq.heappop(pq)
			if ind not in visited:
				ret += cnt
				visited.add(ind)
				for nei in dist[ind]:
					if nei not in visited:
						heapq.heappush(pq, (dist[ind][nei], nei))
		return ret


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def find(a):
			if parents[a] != a:
				return find(parents[a])
			return a

		def union(a, b):
			xa = find(a)
			xb = find(b)
			if xa == xb:
				return
			if rank[xa] > rank[xb]:
				parents[xb] = xa
			elif rank[xa] < rank[xb]:
				parents[xa] = xb
			else:
				parents[xa] = xb
				rank[xb] += 1
		n = len(points)
		parents = [i for i in range(n)]
		rank = [i for i in range(n)]
		edges = []
		for i in range(n):
			for j in range(i + 1, n):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				edges.append((dist, i, j))
		edges.sort()
		res = 0
		for (cost, u, v) in edges:
			if find(u) != find(v):
				union(u, v)
				res += cost
		return res


from heapq import *

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		heap = []
		d = collections.defaultdict(list)
		n = len(points)
		for i in range(n):
			for j in range(i + 1, n):
				x = tuple(points[i])
				y = tuple(points[j])
				distance = abs(x[0] - y[0]) + abs(x[1] - y[1])
				d[x].append((distance, y))
				d[y].append((distance, x))
		start = tuple(points[0])
		heap = d[start].copy()
		heapify(heap)
		(res, s) = (0, set([start]))
		while len(s) < n:
			closest = heappop(heap)
			while closest[1] in s:
				closest = heappop(heap)
			s.add(closest[1])
			res += closest[0]
			for neig in d[closest[1]]:
				if neig not in s:
					heappush(heap, neig)
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) <= 1:
			return 0

		def find(x):
			if x != parent[x]:
				parent[x] = find(parent[x])
				return parent[x]
			return x
		n = len(points)
		parent = list(range(n))
		dists = []
		for i in range(n - 1):
			for j in range(i + 1, n):
				mand = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				heapq.heappush(dists, (mand, i, j))
		res = 0
		while dists:
			(w, a, b) = heapq.heappop(dists)
			pa = find(a)
			pb = find(b)
			if pa != pb:
				res += w
				parent[pa] = parent[pb]
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		costMap = [0] * len(points)
		minHeap = []
		heappush(minHeap, (0, points[0], 0))
		visited = set()
		while minHeap:
			(cost, [currentX, currentY], currentIndex) = heappop(minHeap)
			if (currentX, currentY) in visited:
				if costMap[currentIndex] <= cost:
					continue
			for (i, p) in enumerate(points):
				if not (p[0], p[1]) in visited and i != currentIndex:
					nextCost = abs(currentX - p[0]) + abs(currentY - p[1])
					heappush(minHeap, (nextCost, p, i))
			if (currentX, currentY) in visited:
				costMap[currentIndex] = min(costMap[currentIndex], cost)
			else:
				costMap[currentIndex] = cost
			visited.add((currentX, currentY))
		return sum(costMap)


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		N = len(points)
		distance = []
		for i in range(N):
			for j in range(i + 1, N):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				distance.append((dist, i, j))
		heapq.heapify(distance)
		parent = [i for i in range(N)]

		def find(x):
			while x != parent[x]:
				parent[x] = parent[parent[x]]
				x = parent[x]
			return x
		res = 0
		while distance:
			(dist, i, j) = heapq.heappop(distance)
			pi = find(i)
			pj = find(j)
			if pi != pj:
				parent[pi] = pj
				res += dist
		return res


from heapq import heappush, heappop

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = [[0 for j in range(len(points))] for i in range(len(points))]
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				edges[i][j] = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				edges[j][i] = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
		inf = 1234567890
		frontier = [(0, 0)]
		gotem = set()
		ans = 0
		while len(frontier) > 0:
			(cost, ex) = heappop(frontier)
			if ex in gotem:
				continue
			ans += cost
			gotem.add(ex)
			for i in range(len(points)):
				if i not in gotem and i != ex:
					heappush(frontier, (edges[ex][i], i))
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def cost_of(i, j):
			(x1, y1) = points[i]
			(x2, y2) = points[j]
			return abs(x1 - x2) + abs(y1 - y2)
		N = len(points)
		parent = list(range(N))
		size = [1] * N

		def union(x, y):
			x = find(x)
			y = find(y)
			if x == y:
				return False
			if size[x] < size[y]:
				(x, y) = (y, x)
			parent[y] = x
			size[x] += size[y]
			return True

		def find(x):
			if parent[x] != x:
				parent[x] = find(parent[x])
			return parent[x]
		edges = []
		for i in range(N):
			for j in range(i + 1, N):
				edges.append((cost_of(i, j), i, j))
		heapq.heapify(edges)
		total_cost = 0
		while edges:
			(cost, p1, p2) = heapq.heappop(edges)
			if union(p1, p2):
				total_cost += cost
		return total_cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		N = len(points)
		connections = []
		for i in range(N):
			for j in range(i + 1, N):
				connections.append([abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j])
		if len(connections) < N - 1:
			return -1
		elif N == 1:
			return 0
		uf = {}

		def find(x):
			uf.setdefault(x, x)
			if uf[x] != x:
				uf[x] = find(uf[x])
			return uf[x]

		def union(x, y):
			uf[find(x)] = find(y)
		res = 0
		for (cost, start, end) in sorted(connections):
			if find(start) != find(end):
				res += cost
				union(start, end)
		if len({find(c) for c in uf}) == 1:
			return res
		return -1


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		dsu = DSU()
		min_heap = []
		for i in range(len(points)):
			(x1, y1) = (points[i][0], points[i][1])
			for j in range(i + 1, len(points)):
				(x2, y2) = (points[j][0], points[j][1])
				heappush(min_heap, (abs(x1 - x2) + abs(y1 - y2), (x1, y1, x2, y2)))
		cost = 0
		while min_heap:
			(c, (x1, y1, x2, y2)) = heappop(min_heap)
			if dsu.find((x1, y1)) != dsu.find((x2, y2)):
				cost += c
				dsu.union((x1, y1), (x2, y2))
		return cost

class DSU:

	def __init__(self):
		self.father = {}

	def find(self, a):
		self.father.setdefault(a, a)
		if a != self.father[a]:
			self.father[a] = self.find(self.father[a])
		return self.father[a]

	def union(self, a, b):
		_a = self.find(a)
		_b = self.find(b)
		if _a != _b:
			self.father[_a] = _b


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		e = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				e.append([i, j])

		def h(x):
			return abs(points[x[0]][0] - points[x[1]][0]) + abs(points[x[0]][1] - points[x[1]][1])
		e.sort(key=lambda x: h(x))
		n = len(points)
		v = set()
		s = 0
		c = []

		def find(x):
			nonlocal c
			for (i, cc) in enumerate(c):
				if x in cc:
					return i
		for ee in e:
			(x, y) = ee
			if y not in v and x not in v:
				c.append([x, y])
				v.add(x)
				v.add(y)
				s += h(ee)
			elif x not in v:
				yi = find(y)
				c[yi].append(x)
				v.add(x)
				s += h(ee)
			elif y not in v:
				xi = find(x)
				c[xi].append(y)
				v.add(y)
				s += h(ee)
			else:
				xi = find(x)
				yi = find(y)
				if xi == yi:
					continue
				s += h(ee)
				c[xi] += c[yi]
				del c[yi]
				if len(v) == n and len(c) == 1:
					return s
		return s


class UnionFind:

	def __init__(self, n):
		self.parent = list(range(n))
		self.count = n
		self.rank = [1] * n

	def find(self, p):
		if p != self.parent[p]:
			self.parent[p] = self.find(self.parent[p])
		return self.parent[p]

	def union(self, p, q):
		prt = self.find(p)
		qrt = self.find(q)
		if prt == qrt:
			return False
		if self.rank[prt] > self.rank[qrt]:
			(prt, qrt) = (qrt, prt)
		self.parent[prt] = qrt
		self.rank[qrt] += self.rank[prt]
		return True

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		uf = UnionFind(n)
		hp = []
		for i in range(n):
			(x, y) = points[i]
			for ii in range(i + 1, n):
				(xx, yy) = points[ii]
				cost = abs(x - xx) + abs(y - yy)
				heappush(hp, (cost, i, ii))
		ans = 0
		while hp and uf.count != 1:
			(cost, i, ii) = heappop(hp)
			if uf.union(i, ii):
				ans += cost
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		if n <= 1:
			return 0
		distances = []
		for i in range(n):
			for j in range(i + 1, n):
				(xi, yi) = points[i]
				(xj, yj) = points[j]
				heapq.heappush(distances, (abs(xi - xj) + abs(yi - yj), i, j))
		uf = {}

		def find(i: int) -> int:
			if i not in uf:
				uf[i] = i
			while uf[i] != uf[uf[i]]:
				uf[i] = find(uf[i])
			return uf[i]

		def union(i: int, j: int) -> None:
			uf[find(i)] = find(j)
		dist = 0
		while distances:
			(d, i, j) = heapq.heappop(distances)
			if find(i) != find(j):
				union(i, j)
				dist += d
		return dist


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		parents = [i for i in range(len(points))]
		pq = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				(x, y) = (points[i], points[j])
				heapq.heappush(pq, (abs(x[0] - y[0]) + abs(x[1] - y[1]), i, j))
		res = 0
		while pq:
			(dist, i, j) = heapq.heappop(pq)
			if self.find(i, parents) == self.find(j, parents):
				continue
			res += dist
			self.union(i, j, parents)
		return res

	def find(self, p, parents):
		while p != parents[p]:
			parents[p] = parents[parents[p]]
			p = parents[p]
		return p

	def union(self, p, q, parents):
		p_root = self.find(p, parents)
		q_root = self.find(q, parents)
		if p_root != q_root:
			parents[p_root] = q_root


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		(n, curr, ans) = (len(points), 0, 0)
		cost = [math.inf] * n
		used = set()
		for i in range(n - 1):
			(x, y) = points[curr]
			used.add(curr)
			for (j, (u, v)) in enumerate(points):
				if j in used:
					continue
				cost[j] = min(cost[j], abs(u - x) + abs(v - y))
			(delta, curr) = min(((d, j) for (j, d) in enumerate(cost)))
			cost[curr] = math.inf
			ans += delta
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		if n == 1:
			return 0
		heap = []
		dsu = DisjointSetUnion(n)
		for i in range(n - 1):
			for j in range(i + 1, n):
				distance = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				heappush(heap, (distance, i, j))
		ans = 0
		while heap:
			(distance, i, j) = heappop(heap)
			if dsu.find(i) != dsu.find(j):
				ans += distance
				dsu.union(i, j)
		return ans

class DisjointSetUnion(object):

	def __init__(self, size):
		self.parent = [i for i in range(size + 1)]
		self.size = [1] * (size + 1)

	def find(self, x):
		if self.parent[x] != x:
			self.parent[x] = self.find(self.parent[x])
		return self.parent[x]

	def union(self, x, y):
		(px, py) = (self.find(x), self.find(y))
		if px == py:
			return px
		if self.size[px] > self.size[py]:
			(px, py) = (py, px)
		self.parent[px] = py
		self.size[py] += self.size[px]
		return py


class dsu:

	def __init__(self, n):
		self.parents = [i for i in range(n)]
		self.rank = [0 for i in range(n)]

	def find(self, u):
		if u != self.parents[u]:
			self.parents[u] = self.find(self.parents[u])
		return self.parents[u]

	def union(self, u, v):
		pu = self.parents[u]
		pv = self.parents[v]
		if pu != pv:
			if self.rank[pu] < self.rank[pv]:
				self.parents[pu] = pv
			elif self.rank[pu] > self.rank[pv]:
				self.parents[pv] = pu
			else:
				self.parents[pu] = pv
				self.rank[pv] += 1

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def get_dist(i, j):
			return abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
		h = []
		n = len(points)
		uf = dsu(n)
		for i in range(n):
			for j in range(i):
				heapq.heappush(h, (get_dist(i, j), i, j))
		cost = 0
		count = 0
		while h:
			(c, u, v) = heapq.heappop(h)
			if uf.find(u) != uf.find(v):
				uf.union(u, v)
				cost += c
				count += 1
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		eg = defaultdict(list)
		n = len(points)
		for i in range(n):
			for j in range(n):
				if i != j:
					eg[i].append([j, abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])])
		(d, q) = ({}, [[0, 0]])
		while q:
			(dis, a) = heapq.heappop(q)
			if a not in d:
				d[a] = dis
				for (b, c) in eg[a]:
					if b not in d:
						heapq.heappush(q, [c, b])
		return sum(d.values())


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) == 1:
			return 0
		heap = []
		f = [d for d in range(len(points))]

		def find(x):
			if x != f[x]:
				f[x] = find(f[x])
			return f[x]

		def union(x, y):
			f[find(x)] = find(y)
		res = 0
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				heapq.heappush(heap, (abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j))
		while heap:
			(val, i, j) = heapq.heappop(heap)
			if find(i) != find(j):
				union(i, j)
				res += val
		return res


class UnionFind:

	def __init__(self, n):
		self.parents = [i for i in range(n)]

	def find(self, x):
		if self.parents[x] == x:
			return x
		self.parents[x] = self.find(self.parents[x])
		return self.parents[x]

	def union(self, x, y):
		px = self.find(x)
		py = self.find(y)
		if px != py:
			self.parents[py] = px

	def connected(self, x, y):
		return self.find(x) == self.find(y)

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		graph = []
		uf = UnionFind(len(points))
		res = 0
		for i in range(len(points)):
			for j in range(len(points)):
				if i != j:
					graph.append((i, j, abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])))
		graph.sort(key=lambda x: x[2])
		for (i, j, w) in graph:
			if not uf.connected(i, j):
				uf.union(i, j)
				res += w
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def dist(i, j):
			(p1, p2) = (points[i], points[j])
			res = abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
			return res
		graph = collections.defaultdict(list)
		for i in range(len(points)):
			for j in range(len(points)):
				if i != j:
					graph[i].append((dist(i, j), j))
		visited = set([])
		root = 0
		visited.add(root)
		edges = [pair for pair in graph[root]]
		res = 0
		heapq.heapify(edges)
		while edges:
			(cost, nex) = heapq.heappop(edges)
			if nex not in visited:
				res += cost
				visited.add(nex)
				for pair in graph[nex]:
					if pair[1] not in visited:
						heapq.heappush(edges, pair)
		return res


class Solution:
	parents = [i for i in range(1005)]

	def findParent(i):
		if Solution.parents[i] != i:
			Solution.parents[i] = Solution.findParent(Solution.parents[i])
		return Solution.parents[i]

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		distances = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				distance = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				distances.append([distance, i, j])
		distances.sort()
		ans = 0
		for distance in distances:
			if Solution.findParent(distance[1]) != Solution.findParent(distance[2]):
				Solution.parents[Solution.parents[distance[1]]] = Solution.parents[Solution.parents[distance[2]]]
				ans += distance[0]
		Solution.parents = [i for i in range(1005)]
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def manhattan(p1, p2):
			return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		g = collections.defaultdict(list)
		n = len(points)
		for i in range(n):
			for j in range(n):
				if i != j:
					g[i].append((manhattan(points[i], points[j]), j))
		heap = [(0, 0)]
		ans = 0
		visited = set()
		while heap:
			(weight, to) = heapq.heappop(heap)
			if to in visited:
				continue
			ans += weight
			visited.add(to)
			for (cost, nei) in g[to]:
				if nei not in visited:
					heapq.heappush(heap, (cost, nei))
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) <= 1:
			return 0
		ans = 0
		par = {}

		def find(x):
			if x not in par:
				return x
			res = find(par[x])
			par[x] = res
			return res

		def union(a, b):
			n1 = find(a)
			n2 = find(b)
			if n1 != n2:
				if n1 < n2:
					par[n2] = n1
				else:
					par[n1] = n2
				return True
			else:
				return False
		arr = set()
		for i in range(len(points)):
			_min = 10000000000.0
			ix = -1
			for j in range(len(points)):
				if i != j:
					n = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
					arr.add((n, (min(i, j), max(i, j))))
					if n < _min:
						ix = j
						_min = n
			if union(i, ix):
				ans += _min
		arr = list(arr)
		arr.sort()
		for x in arr:
			i = x[1][0]
			j = x[1][1]
			n1 = find(i)
			n2 = find(j)
			if n1 != n2:
				union(i, j)
				ans += x[0]
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		if len(points) == 1:
			return 0
		res = 0
		curr = 0
		dis = [math.inf] * n
		explored = set()
		for _ in range(n - 1):
			(x0, y0) = points[curr]
			explored.add(curr)
			for (j, (x, y)) in enumerate(points):
				if j in explored:
					continue
				dis[j] = min(dis[j], abs(x - x0) + abs(y - y0))
			(delta, curr) = min(((d, j) for (j, d) in enumerate(dis)))
			dis[curr] = math.inf
			res += delta
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		l = len(points)
		h = []
		for i in range(l):
			for j in range(i):
				((x1, y1), (x2, y2)) = (points[i], points[j])
				dis = abs(x1 - x2) + abs(y1 - y2)
				heapq.heappush(h, [dis, i, j])
		dp = [i for i in range(l)]

		def find(x):
			if dp[x] != x:
				dp[x] = find(dp[x])
			return dp[x]
		ans = 0
		while h:
			(dis, x, y) = heapq.heappop(h)
			if find(x) != find(y):
				ans += dis
			dp[find(x)] = find(y)
		return ans


from typing import List
import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		(n, cost) = (len(points), 0)
		p = list(range(n))
		arr = []
		for i in range(n):
			for j in range(i + 1, n):
				heapq.heappush(arr, [abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j])

		def find(x):
			if x != p[x]:
				p[x] = find(p[p[x]])
			return p[x]
		while arr:
			(w, i, j) = heapq.heappop(arr)
			(i, j) = (find(i), find(j))
			if i == j:
				continue
			cost += w
			p[i] = j
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		min_cost = 0
		msp = set()
		distances = self.compute_all_distances(points)
		groups = defaultdict(set)
		for i in range(len(points)):
			groups[i].add(i)
		while distances:
			next_min = heapq.heappop(distances)
			g1 = self.find_group(groups, next_min[1])
			g2 = self.find_group(groups, next_min[2])
			if g1 != g2:
				min_cost += next_min[0]
				groups[g1] = groups[g1] | groups[g2]
				del groups[g2]
		return min_cost

	def find_group(self, groups: dict, i: int) -> int:
		for group in groups:
			if i in groups[group]:
				return group
		return 0

	def compute_all_distances(self, points: List[List[int]]) -> List[int]:
		distances = list()
		for i in range(len(points) - 1):
			p1 = points[i]
			for j in range(i + 1, len(points)):
				p2 = points[j]
				d = self.dist(p1, p2)
				distances.append((d, i, j))
		heapq.heapify(distances)
		return distances

	def dist(self, p1: List[int], p2: List[int]) -> int:
		return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		dis = lambda x, y, x1, y1: abs(x - x1) + abs(y - y1)
		distances = []
		for (i, (x, y)) in enumerate(points):
			for (x1, y1) in points[i + 1:]:
				d = dis(x, y, x1, y1)
				distances.append((d, x, y, x1, y1))
		uf = UnionFind(len(points))
		for (x, y) in points:
			uf.parents[x, y] = (x, y)
		distances.sort()
		ans = 0
		for (d, x, y, x1, y1) in distances:
			if uf.union((x, y), (x1, y1)):
				ans += d
		return ans

class UnionFind:

	def __init__(self, n):
		self.component_count = n
		self.parents = {}

	def find(self, x):
		if self.parents[x] != x:
			self.parents[x] = self.find(self.parents[x])
		return self.parents[x]

	def union(self, x, y):
		x0 = self.find(x)
		y0 = self.find(y)
		if x0 == y0:
			return False
		self.parents[y0] = x0
		return True


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def dist(i, j):
			return abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
		n = len(points)
		fa = [i for i in range(n)]

		def findfa(x):
			if fa[x] == x:
				return x
			else:
				fa[x] = findfa(fa[x])
				return fa[x]
		e = [(dist(i, j), i, j) for j in range(n) for i in range(n)]
		e.sort()
		ans = 0
		for edge in e:
			if findfa(edge[1]) != findfa(edge[2]):
				ans += edge[0]
				fa[findfa(edge[1])] = findfa(edge[2])
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		N = len(points)
		graph = defaultdict(list)
		start = 0
		for src in range(N):
			for dst in range(N):
				wt = abs(points[src][0] - points[dst][0]) + abs(points[src][1] - points[dst][1])
				graph[src].append((dst, wt))
		dist = {}
		heap = [(0, start)]
		while heap:
			(ddist, node) = heapq.heappop(heap)
			if node in dist:
				continue
			dist[node] = ddist
			for (neighbor, d) in graph[node]:
				if neighbor not in dist:
					heapq.heappush(heap, (d, neighbor))
		return sum(dist.values())


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		manhattan = lambda x, y: abs(x[0] - y[0]) + abs(x[1] - y[1])
		(res, length, heap, visited) = (0, len(points), [(0, 0)], set())
		while len(visited) < length:
			(w, u) = heapq.heappop(heap)
			if u not in visited:
				res += w
				visited.add(u)
				for v in range(length):
					if v not in visited:
						heapq.heappush(heap, (manhattan(points[u], points[v]), v))
		return res


class Solution:

	def find(self, pt):
		if pt == self.roots[pt]:
			return pt
		self.roots[pt] = self.find(self.roots[pt])
		return self.roots[pt]

	def union(self, p1, p2):
		(parent1, parent2) = (self.find(p1), self.find(p2))
		if parent1 == parent2:
			return False
		if self.rank[parent2] < self.rank[parent1]:
			(parent1, parent2) = (parent2, parent1)
			(p1, p2) = (p2, p1)
		if self.rank[parent1] == self.rank[parent2]:
			self.rank[parent2] += 1
		self.roots[parent1] = parent2
		return True

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		self.roots = {(x, y): (x, y) for (x, y) in points}
		self.rank = {(x, y): 0 for (x, y) in points}
		ans = 0
		edges = []
		for i in range(len(points)):
			p1 = (points[i][0], points[i][1])
			for j in range(i + 1, len(points)):
				p2 = (points[j][0], points[j][1])
				dist = abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
				edges.append((dist, p1, p2))
		edges.sort()
		for (dist, p1, p2) in edges:
			if self.union(p1, p2):
				ans += dist
		return ans


import heapq

class DSU:

	def __init__(self, n):
		self.roots = [i for i in range(n)]

	def find(self, x):
		if self.roots[x] != x:
			self.roots[x] = self.find(self.roots[x])
		return self.roots[x]

	def union(self, x, y):
		self.roots[self.find(x)] = self.find(y)

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		if n == 1:
			return 0
		heap = []
		for i in range(n - 1):
			for j in range(i + 1, n):
				(ax, ay) = points[i]
				(bx, by) = points[j]
				heapq.heappush(heap, [abs(ax - bx) + abs(ay - by), i, j])
		count = 0
		dsu = DSU(n)
		while heapq:
			(dist, i, j) = heapq.heappop(heap)
			if dsu.find(i) != dsu.find(j):
				count += dist
				dsu.union(i, j)
			for i in range(n):
				dsu.find(i)
			if len(set(dsu.roots)) == 1:
				break
		return count


class Solution:

	def d(self, p1, p2):
		return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		f = [[x] for x in points]
		c = [float('inf') for x in points]
		g = [-1 for x in points]
		r = []
		while len(f) > 1:
			i = 0
			c = [float('inf') for x in f]
			while i < len(f):
				dx = -1
				j = 0
				while j < len(f):
					if i != j:
						for x in f[i]:
							for y in f[j]:
								val = self.d(x, y)
								if val < c[i]:
									c[i] = val
									g[i] = i
									dx = j
					j += 1
				if dx != -1:
					r.append(c[i])
					f[i] += f[dx]
					del f[dx]
					del c[dx]
					del g[dx]
					i -= 1
				i += 1
		return sum(r)


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		N = len(points)
		dis = [[0] * N for _ in range(N)]
		for i in range(N):
			for j in range(N):
				if i == j:
					continue
				dis[i][j] = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
		vis = [False] * N
		heap = [(0, 0)]
		res = 0
		while heap:
			(weight, node) = heapq.heappop(heap)
			if vis[node]:
				continue
			vis[node] = True
			res += weight
			for i in range(N):
				if vis[i]:
					continue
				heapq.heappush(heap, (dis[node][i], i))
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)

		def find(x):
			if par[x] == x:
				return x
			par[x] = find(par[x])
			return par[x]

		def union(x, y):
			(a, b) = (find(x), find(y))
			if a == b:
				return False
			par[a] = b
			return True
		edges = []
		for i in range(n):
			for j in range(i + 1, n):
				edges.append([abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j])
		edges.sort()
		par = [i for i in range(n)]
		ans = 0
		for i in edges:
			(d, u, v) = (i[0], i[1], i[2])
			if union(u, v):
				ans += d
		return ans


from heapq import *

class Solution:

	def minCostConnectPoints(self, points):
		N = len(points)
		parent = [i for i in range(N)]

		def find(v):
			while parent[v] != parent[parent[v]]:
				parent[v] = parent[parent[v]]
			return parent[v]
		dist = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		(heap, total_cost) = ([], 0)
		for u in range(N - 1):
			for v in range(u + 1, N):
				heappush(heap, [dist(points[u], points[v]), u, v])
		while heap:
			(cost, u, v) = heappop(heap)
			(pu, pv) = (find(u), find(v))
			if pu != pv:
				parent[pu] = pv
				N -= 1
				total_cost += cost
				if N == 0:
					break
		return total_cost
from heapq import *

class Solution:

	def minCostConnectPoints(self, points):
		dist = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		N = len(points)
		parent = [i for i in range(N)]

		def find(v):
			while parent[v] != parent[parent[v]]:
				parent[v] = parent[parent[v]]
			return parent[v]
		heap = []
		for i in range(N - 1):
			for j in range(i + 1, N):
				heappush(heap, (dist(points[i], points[j]), i, j))
		res = 0
		while heap:
			(d, u, v) = heappop(heap)
			(pu, pv) = (find(u), find(v))
			if pu != pv:
				parent[pu] = pv
				res += d
				N -= 1
				if N == 0:
					break
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		(hp, uf) = ([], UF(len(points)))
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				(p1, p2) = (points[i], points[j])
				weight = abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
				heapq.heappush(hp, (weight, i, j))
		res = 0
		while hp:
			(weight, a, b) = heapq.heappop(hp)
			if uf.find(a) != uf.find(b):
				uf.union(a, b)
				res += weight
		return res

class UF:

	def __init__(self, n):
		self.uf = list(range(n))
		self.sz = [1] * n
		self.root_cnt = n

	def find(self, c):
		root = c
		while root != self.uf[root]:
			root = self.uf[root]
		while self.uf[c] != root:
			p = self.uf[c]
			self.uf[c] = root
			c = p
		return root

	def union(self, a, b):
		(ra, rb) = (self.find(a), self.find(b))
		if ra == rb:
			return False
		if self.sz[ra] < self.sz[rb]:
			self.uf[ra] = rb
			self.sz[rb] += self.sz[ra]
		else:
			self.uf[rb] = ra
			self.sz[ra] += self.sz[rb]
		self.root_cnt -= 1
		return True


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def manhattan(p1, p2):
			(x1, y1) = p1
			(x2, y2) = p2
			return abs(x1 - x2) + abs(y1 - y2)
		s = len(points)
		components = [i for i in range(s)]
		costs = [(manhattan(points[j], points[i]), j, i) for i in range(s) for j in range(s)]
		costs = sorted(costs, key=lambda x: x[0])
		totalCost = 0
		for (c, p1, p2) in costs:
			if p1 != p2:
				if not self.find(p1, p2, components):
					self.union(p1, p2, components)
					totalCost += c
		return totalCost

	def root(self, a, roots):
		while roots[a] != a:
			roots[a] = roots[roots[a]]
			a = roots[a]
		return a

	def find(self, a, b, roots):
		return self.root(a, roots) == self.root(b, roots)

	def union(self, a, b, roots):
		ra = self.root(a, roots)
		rb = self.root(b, roots)
		roots[rb] = ra


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		total = 0
		edges = []
		N = len(points)
		parent = [x for x in range(N)]

		def ufind(x):
			if parent[x] != x:
				return ufind(parent[x])
			return x

		def uunion(x, y):
			ux = ufind(x)
			uy = ufind(y)
			parent[uy] = ux

		def dist(xi, yi, xj, yj):
			return abs(xi - xj) + abs(yi - yj)
		for i in range(N):
			(xi, yi) = points[i]
			for j in range(i + 1, N):
				(xj, yj) = points[j]
				edges.append((dist(xi, yi, xj, yj), i, j))
		edges.sort()
		for (edge, i, j) in edges:
			if ufind(i) != ufind(j):
				uunion(i, j)
				total += edge
		return total


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def find(e1):
			if a[e1] == -1:
				return e1
			return find(a[e1])
		n = len(points)
		a = [-1] * n

		def dist(i, j):
			return abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
		temp = []
		for i in range(n):
			for j in range(i + 1, n):
				temp.append((dist(i, j), i, j))
		temp.sort()
		ans = 0
		for (d, x, y) in temp:
			(u1, u2) = (find(x), find(y))
			if u1 != u2:
				a[u2] = u1
				ans += d
		return ans


import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def dis(s, e):
			return abs(s[0] - e[0]) + abs(s[1] - e[1])

		def find(u):
			if root[u] != u:
				root[u] = find(root[u])
			return root[u]

		def union(u, v):
			(ru, rv) = (find(u), find(v))
			if ru == rv:
				return False
			if rank[ru] < rank[rv]:
				root[ru] = rv
				rank[rv] = rank[ru] + rank[rv]
			else:
				root[rv] = ru
				rank[ru] = rank[ru] + rank[rv]
			return True
		n = len(points)
		res = 0
		queue = []
		root = [i for i in range(n)]
		rank = [1] * n
		for i in range(n):
			s = points[i]
			for j in range(i + 1, n):
				e = points[j]
				heapq.heappush(queue, (dis(s, e), i, j))
		while queue:
			(dis, s, e) = heapq.heappop(queue)
			if union(s, e):
				res += dis
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		ll = len(points)
		if ll == 1:
			return 0
		distances = []

		def get_distance(i, j):
			return abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
		for i in range(ll):
			for j in range(i + 1, ll):
				distances.append((get_distance(i, j), i, j))
		distances.sort()
		parents = list(range(len(points)))

		def ufind(x):
			if parents[x] != x:
				return ufind(parents[x])
			return x

		def uunion(x, y):
			ux = ufind(x)
			uy = ufind(y)
			parents[uy] = ux
		res = 0
		for (d, x, y) in distances:
			ux = ufind(x)
			uy = ufind(y)
			if ux != uy:
				uunion(ux, uy)
				res += d
		return res


class UnionFind:

	def __init__(self, n):
		self.parent = list(range(n))

	def find(self, x):
		if self.parent[x] != x:
			self.parent[x] = self.find(self.parent[x])
		return self.parent[x]

	def union(self, x, y):
		(px, py) = (self.find(x), self.find(y))
		if px == py:
			return False
		self.parent[px] = py
		return True

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		(n, res, pq) = (len(points), 0, list())
		for i in range(n):
			for j in range(i + 1, n):
				d = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				heapq.heappush(pq, (d, i, j))
		uf = UnionFind(n)
		while pq:
			(d, i, j) = heapq.heappop(pq)
			if uf.union(i, j):
				res += d
		return res


class DSU:

	def __init__(self, N):
		self.parents = list(range(N))
		self.size = [1] * N

	def __find(self, x):
		if self.parents[x] != x:
			self.parents[x] = self.__find(self.parents[x])
		return self.parents[x]

	def union(self, x, y):
		x = self.__find(x)
		y = self.__find(y)
		if x == y:
			return False
		if self.size[x] < self.size[y]:
			(x, y) = (y, x)
		self.parents[y] = x
		self.size[x] += self.size[y]
		return True

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []

		def kruskals(N, edges):
			cost = 0
			dsu = DSU(N)
			for (i, j, dist) in edges:
				if dsu.union(i, j):
					cost += dist
			return cost
		for (i, (x, y)) in enumerate(points):
			for (j, (x1, y1)) in enumerate(points):
				if i != j:
					dist = abs(x1 - x) + abs(y1 - y)
					edges.append([i, j, dist])
		edges.sort(key=lambda v: v[2])
		return kruskals(len(points), edges)


import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		(N, g) = (len(points), [])
		res = 0
		for i in range(N - 1):
			(x0, y0) = points[i]
			for j in range(i + 1, N):
				(x1, y1) = points[j]
				dist = abs(x0 - x1) + abs(y0 - y1)
				g.append((dist, (i, j)))
		heapq.heapify(g)
		parents = [None] * N
		for i in range(N):
			parents[i] = i

		def findParent(x):
			if parents[x] != x:
				parents[x] = findParent(parents[x])
			return parents[x]
		while g:
			(w, (a, b)) = heapq.heappop(g)
			pa = findParent(a)
			pb = findParent(b)
			if pa != pb:
				res += w
				parents[pa] = pb
		return res


class UnionFind:

	def __init__(self, n):
		self.p = list(range(n))

	def find(self, i):
		if self.p[i] != i:
			self.p[i] = self.find(self.p[i])
		return self.p[i]

	def union(self, x, y):
		(rx, ry) = (self.find(x), self.find(y))
		self.p[rx] = ry

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) < 2:
			return 0
		hq = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				heapq.heappush(hq, (dist, i, j))
		connect = 0
		uf = UnionFind(len(points))
		cost = 0
		while connect != len(points) - 1 and hq:
			(d, i, j) = heapq.heappop(hq)
			(ri, rj) = (uf.find(i), uf.find(j))
			if ri != rj:
				cost += d
				uf.union(i, j)
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		if len(points) == 1:
			return 0
		res = 0
		curr = 0
		dis = [math.inf] * n
		explored = set()
		for i in range(n - 1):
			(x0, y0) = points[curr]
			explored.add(curr)
			for (j, (x, y)) in enumerate(points):
				if j in explored:
					continue
				dis[j] = min(dis[j], abs(x - x0) + abs(y - y0))
			(delta, curr) = min(((d, j) for (j, d) in enumerate(dis)))
			dis[curr] = math.inf
			res += delta
		return res

	def minCostConnectPoints2(self, P: List[List[int]]) -> int:
		res = 0
		n = len(P)
		(px, py) = P[0]
		seen = {0}
		todo = set(range(1, n))
		while len(seen) < n:
			mn = float('inf')
			used = -1
			for i in todo:
				(cx, cy) = P[i]
				for j in seen:
					(px, py) = P[j]
					can = abs(cx - px) + abs(cy - py)
					if can < mn:
						mn = can
						used = i
			res += mn
			todo.remove(used)
			seen.add(used)
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		dists = []
		n = len(points)
		for i in range(n - 1):
			(x1, y1) = points[i]
			for j in range(i + 1, n):
				(x2, y2) = points[j]
				dists.append((abs(x1 - x2) + abs(y1 - y2), i, j))
		roots = [-1] * n

		def find(p1):
			while roots[p1] >= 0:
				p1 = roots[p1]
			return p1

		def union(r1, r2):
			if roots[r1] < roots[r2]:
				roots[r1] += roots[r2]
				roots[r2] = r1
			else:
				roots[r2] += roots[r1]
				roots[r1] = r2
		res = 0
		heapq.heapify(dists)
		while dists:
			(dist, p1, p2) = heapq.heappop(dists)
			r1 = find(p1)
			r2 = find(p2)
			if r1 != r2:
				union(r1, r2)
				res += dist
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		total = 0
		edges = []
		N = len(points)
		parent = [x for x in range(N)]
		rank = [1 for x in range(N)]

		def ufind(x):
			if parent[x] == x:
				return parent[x]
			return ufind(parent[x])

		def uunion(x, y):
			ux = ufind(x)
			uy = ufind(y)
			if rank[ux] > rank[uy]:
				parent[uy] = ux
				rank[ux] += rank[uy]
			else:
				parent[ux] = uy
				rank[uy] += rank[ux]

		def dist(xi, yi, xj, yj):
			return abs(xi - xj) + abs(yi - yj)
		for i in range(N):
			(xi, yi) = points[i]
			for j in range(i + 1, N):
				(xj, yj) = points[j]
				edges.append((dist(xi, yi, xj, yj), i, j))
		heapq.heapify(edges)
		for v in range(len(edges)):
			(edge, i, j) = heapq.heappop(edges)
			if ufind(i) != ufind(j):
				uunion(i, j)
				total += edge
		return total


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		d = {}
		min_heap = []
		n = len(points)
		for i in range(n):
			for j in range(i + 1, n):
				(x1, y1) = (points[i][0], points[i][1])
				(x2, y2) = (points[j][0], points[j][1])
				dist = abs(x1 - x2) + abs(y1 - y2)
				d[x1, y1] = (x1, y1)
				d[x2, y2] = (x2, y2)
				heapq.heappush(min_heap, (dist, (x1, y1), (x2, y2)))

		def find(x):
			px = d[x]
			if px != x:
				d[x] = find(px)
			return d[x]

		def union(x, y):
			(px, py) = (find(x), find(y))
			if px != py:
				d[px] = py
		min_cost = 0
		while min_heap:
			(c, p1, p2) = heapq.heappop(min_heap)
			(pa1, pa2) = (find(p1), find(p2))
			if pa1 != pa2:
				union(p1, p2)
				min_cost += c
		return min_cost


from queue import PriorityQueue

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		q = []
		N = len(points)
		for i in range(N):
			for j in range(i + 1, N):
				(a, b) = points[i]
				(c, d) = points[j]
				dist = abs(a - c) + abs(b - d)
				q.append((dist, i, j))
		heapify(q)
		ans = 0
		par = list(range(N))
		rank = [0] * N

		def find_parent(a):
			if par[a] == a:
				return a
			par[a] = find_parent(par[a])
			return par[a]

		def join(a, b):
			(pa, pb) = (find_parent(a), find_parent(b))
			if pa == pb:
				return 0
			if rank[pa] < rank[pb]:
				par[pa] = pb
			elif rank[pa] > rank[pb]:
				par[pb] = pa
			else:
				par[pb] = pa
				rank[pa] += 1
			return 1
		while q:
			(dist, i, j) = heappop(q)
			if join(i, j):
				ans += dist
		return ans


class DSU:

	def __init__(self, n):
		self.parents = [i for i in range(n)]
		self.sizes = [1] * n

	def find(self, x):
		p = self.parents[x]
		if p == x:
			return x
		self.parents[x] = self.find(p)
		return self.parents[x]

	def union(self, x, y):
		(px, py) = (self.find(x), self.find(y))
		if px == py:
			return False
		(sx, sy) = (self.sizes[px], self.sizes[py])
		if sy > sx:
			(px, py) = (py, px)
		self.parents[py] = px
		self.sizes[px] = sx + sy
		return True

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []
		for (i1, p1) in enumerate(points):
			for i2 in range(i1 + 1, len(points)):
				p2 = points[i2]
				d = abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
				edges.append([d, i1, i2])
		edges.sort()
		dsu = DSU(len(points))
		t = 0
		for (c, i1, i2) in edges:
			if dsu.union(i1, i2):
				t += c
		return t


class UnionFind:

	def __init__(self, size):
		self.parent = [i for i in range(size)]
		self.rank = [1] * size

	def find(self, x):
		if x != self.parent[x]:
			self.parent[x] = self.find(self.parent[x])
		return self.parent[x]

	def union(self, x, y):
		(p_x, p_y) = (self.find(x), self.find(y))
		if p_x == p_y:
			return
		if self.rank[p_x] < self.rank[p_y]:
			self.parent[p_x] = p_y
			self.rank[p_y] += self.rank[p_x]
		else:
			self.parent[p_y] = p_x
			self.rank[p_x] += self.rank[p_y]

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		edge_list = []
		for i in range(n):
			for j in range(n):
				if i != j:
					edge_list.append([i, j, self.dist(points[i], points[j])])
		uf = UnionFind(n)
		cost = 0
		edge_list.sort(key=lambda x: x[2])
		for (u, v, w) in edge_list:
			(p_u, p_v) = (uf.find(u), uf.find(v))
			if p_u == p_v:
				continue
			uf.union(u, v)
			cost += w
		return cost

	def dist(self, point1, point2):
		return abs(point1[0] - point2[0]) + abs(point1[1] - point2[1])


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		graph = defaultdict(list)
		visited = set()
		res = 0
		for (idx1, point1) in enumerate(points):
			for (idx2, point2) in enumerate(points):
				if idx1 != idx2:
					man = abs(point1[0] - point2[0]) + abs(point1[1] - point2[1])
					graph[idx1].append((man, idx2))
					graph[idx2].append((man, idx1))
		con = set([0])
		heap = graph[0][:]
		heapify(heap)
		while len(con) != len(points):
			while heap:
				cur = heappop(heap)
				if cur[1] not in con:
					for neig in graph[cur[1]]:
						heappush(heap, neig)
					con.add(cur[1])
					res += cur[0]
					break
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		p = [0] * len(points)
		for i in range(len(points)):
			p[i] = i
		pq = []
		for i in range(len(points) - 1):
			for j in range(i + 1, len(points)):
				dis = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				heapq.heappush(pq, [dis, i, j])

		def find(x):
			if p[x] != x:
				p[x] = find(p[x])
			return p[x]

		def union(x, y):
			if x > y:
				(x, y) = (y, x)
			p[y] = x
		res = 0
		while len(pq) > 0:
			(dis, i, j) = heapq.heappop(pq)
			if find(i) == find(j):
				continue
			res += dis
			union(find(i), find(j))
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		parents = [i for i in range(n)]
		groups = n

		def find(x):
			if parents[x] != x:
				parents[x] = find(parents[x])
			return parents[x]
		distance = 0
		heap = []
		for i in range(n):
			for j in range(i):
				heapq.heappush(heap, (abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j))
		while heap or groups > 1:
			(dist, i, j) = heapq.heappop(heap)
			(ri, rj) = (find(i), find(j))
			if ri != rj:
				groups -= 1
				parents[ri] = rj
				distance += dist
		return distance


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		graph = []
		self.parent = [i for i in range(len(points))]
		cost = 0
		for i in range(len(points) - 1):
			for j in range(len(points)):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				graph.append([i, j, dist])
		graph = sorted(graph, key=lambda x: x[2])
		for (u, v, c) in graph:
			if self.union(u, v):
				cost += c
		return cost

	def union(self, x, y):
		parentX = self.find(x)
		parentY = self.find(y)
		if parentX == parentY:
			return False
		if self.parent[parentX] <= self.parent[parentY]:
			self.parent[parentY] = parentX
		else:
			self.parent[parentX] = parentY
		return True

	def find(self, x):
		if self.parent[x] != x:
			self.parent[x] = self.find(self.parent[x])
		return self.parent[x]


from heapq import heappush, heappop

class UnionFind:

	def __init__(self, n):
		self.group = list(range(n))
		self.size = [0] * n

	def find(self, i):
		if i == self.group[i]:
			return i
		p = self.find(self.group[i])
		self.group[i] = p
		return p

	def union(self, i, j):
		i = self.find(i)
		j = self.find(j)
		if self.size[i] <= self.size[j]:
			self.group[i] = j
			self.size[j] += self.size[i]
		else:
			self.group[j] = i
			self.size[i] += self.size[j]

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		weights = []
		for i in range(len(points) - 1):
			for j in range(i + 1, len(points)):
				weight = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				heappush(weights, (weight, i, j))
		uf = UnionFind(len(points))
		res = 0
		while weights:
			(min_edge, i, j) = heappop(weights)
			if uf.find(i) == uf.find(j):
				continue
			uf.union(i, j)
			res += min_edge
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def cal(p1, p2):
			return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		(d, q) = ({}, [[0, 0]])
		ans = 0
		while q:
			(dis, a) = heapq.heappop(q)
			if a not in d:
				d[a] = dis
				ans += dis
				for b in range(len(points)):
					if b not in d:
						heapq.heappush(q, [cal(points[a], points[b]), b])
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		parent = collections.defaultdict(int)

		def find(p):
			if parent[p] == 0:
				return p
			return find(parent[p])

		def union(p1, p2):
			if p1 != p2:
				if p1 < p2:
					parent[p2] = p1
				else:
					parent[p1] = p2
		V = points
		E = []
		for p1 in V:
			for p2 in V:
				if p1 != p2:
					E.append((tuple(p1), tuple(p2)))
		W = {}
		for edge in E:
			W[edge] = abs(edge[0][0] - edge[1][0]) + abs(edge[0][1] - edge[1][1])
		sorted_W = {k: v for (k, v) in sorted(W.items(), key=lambda item: item[1])}
		count = 0
		cost = 0
		for e in sorted_W:
			(x, y) = (e[0], e[1])
			(x_set, y_set) = (find(x), find(y))
			if x_set != y_set:
				union(x_set, y_set)
				count += 1
				cost += sorted_W[e]
			if count == len(V) - 1:
				break
		return cost


class Solution:

	def calculateDistance(self, point1, point2):
		return abs(point1[0] - point2[0]) + abs(point1[1] - point2[1])

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		queue = []
		queueSet = [0] * len(points)
		setDict = {}
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				heappush(queue, (self.calculateDistance(points[i], points[j]), points[i], points[j]))
			queueSet[i] = [tuple(points[i])]
			setDict[tuple(points[i])] = i
		totalCost = 0
		while queue:
			p = heappop(queue)
			t1 = tuple(p[1])
			t2 = tuple(p[2])
			if setDict[t1] != setDict[t2]:
				totalCost = totalCost + p[0]
				if setDict[t1] < setDict[t2]:
					queueSet[setDict[t1]].extend(queueSet[setDict[t2]])
					for ch in queueSet[setDict[t2]]:
						setDict[ch] = setDict[t1]
					setDict[t2] = setDict[t1]
				else:
					queueSet[setDict[t2]].extend(queueSet[setDict[t1]])
					for ch in queueSet[setDict[t1]]:
						setDict[ch] = setDict[t2]
					setDict[t1] = setDict[t2]
		return totalCost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) == 1:
			return 0
		res = 0
		n = len(points)
		visited = set([0])
		cur = 0
		dist = [float('inf')] * n
		for _ in range(n - 1):
			(x, y) = points[cur]
			for (j, (u, v)) in enumerate(points):
				if j in visited:
					continue
				dist[j] = min(dist[j], abs(x - u) + abs(y - v))
			(d, cur) = min([(d, j) for (j, d) in enumerate(dist)])
			dist[cur] = float('inf')
			res += d
			visited.add(cur)
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		visited = [False] * len(points)
		distance = [[0] * len(points) for p in points]
		queue = [(0, 0)]
		for i in range(len(points)):
			for j in range(len(points)):
				distance[i][j] = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
		res = 0
		while queue:
			(cost, point) = heapq.heappop(queue)
			if visited[point] == True:
				continue
			visited[point] = True
			res += cost
			for i in range(len(points)):
				if not visited[i]:
					heapq.heappush(queue, (distance[point][i], i))
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		parent = {}
		size = defaultdict(lambda : 1)

		def find(u):
			if u != parent.get(u, u):
				parent[u] = find(parent[u])
			return parent.get(u, u)

		def union(u, v):
			(u, v) = (find(u), find(v))
			if u != v:
				if size[u] < size[v]:
					(u, v) = (v, u)
				parent[u] = v
				size[u] += size[v]
		total = 0
		edges = []
		for i in range(len(points)):
			for j in range(len(points)):
				if i != j:
					edges.append((abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j))
		edges.sort()
		for (cost, u, v) in edges:
			if find(u) != find(v):
				total += cost
				union(u, v)
		return total


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def calculate_distance(x1, y1, x2, y2):
			return abs(x1 - x2) + abs(y1 - y2)
		res = 0
		n = len(points)
		visited = set()
		d = defaultdict(list)
		for i in range(n):
			for j in range(n):
				if i != j:
					d[i].append((calculate_distance(points[i][0], points[i][1], points[j][0], points[j][1]), j))
					d[j].append((calculate_distance(points[i][0], points[i][1], points[j][0], points[j][1]), i))
		heap = d[0]
		heapq.heapify(heap)
		visited.add(0)
		count = 1
		while heap and count < n:
			(dist, j) = heapq.heappop(heap)
			if j not in visited:
				visited.add(j)
				res += dist
				count += 1
				for r in d[j]:
					heapq.heappush(heap, r)
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if not points:
			return 0
		n = len(points)
		dist = [[0] * n for _ in range(n)]
		for i in range(n):
			(x1, y1) = points[i]
			for j in range(n):
				(x2, y2) = points[j]
				dist[i][j] = abs(x1 - x2) + abs(y1 - y2)
		origin = 0
		q = []
		for (j, d) in enumerate(dist[0]):
			heapq.heappush(q, (d, j))
		ans = 0
		visited = set([0])
		while q:
			(d, child) = heapq.heappop(q)
			if child not in visited:
				ans += d
				visited.add(child)
				for (j, n_d) in enumerate(dist[child]):
					if j not in visited:
						heapq.heappush(q, (n_d, j))
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		if n == 1:
			return 0
		costs = []
		for i in range(n):
			cost = [0] * n
			costs.append(cost)
		for i in range(n):
			ax = points[i][0]
			ay = points[i][1]
			for j in range(i + 1, n):
				bx = points[j][0]
				by = points[j][1]
				costs[i][j] = abs(ax - bx) + abs(ay - by)
				costs[j][i] = costs[i][j]
		conn = [-1] * n
		for i in range(n):
			for j in range(n):
				cs = costs[i][j]
				if cs != 0:
					if conn[i] == -1:
						conn[i] = j
					elif cs < costs[i][conn[i]]:
						conn[i] = j
		groups = []
		toset = list(range(n))
		conngroupcost = 0
		while len(toset) > 0:
			point = toset[0]
			g = [point]
			toset.remove(point)
			while conn[point] not in g:
				g.append(conn[point])
				conngroupcost += costs[point][conn[point]]
				toset.remove(conn[point])
				point = conn[point]
			while len(toset) > 0:
				npoint = []
				for x in toset:
					if conn[x] in g:
						npoint.append(x)
						g.append(x)
						conngroupcost += costs[x][conn[x]]
				if len(npoint) == 0:
					break
				else:
					for np in npoint:
						toset.remove(np)
			groups.append(g)
		while len(groups) > 1:
			minlen = -1
			minindex = -1
			for gi in range(len(groups)):
				if minlen == -1:
					minlen = len(groups[gi])
					minindex = gi
				elif len(groups[gi]) < minlen:
					minlen = len(groups[gi])
					minindex = gi
			gps = groups[minindex]
			mincost = -1
			mincostp = -1
			for gp in gps:
				for i in range(n):
					if i not in gps:
						if mincost == -1:
							mincost = costs[gp][i]
							mincostp = i
						elif mincost > costs[gp][i]:
							mincost = costs[gp][i]
							mincostp = i
			conngroupcost += mincost
			conngindex = -1
			for gindex in range(len(groups)):
				if mincostp in groups[gindex]:
					conngindex = gindex
					break
			groups[minindex] = groups[minindex] + groups[conngindex]
			del groups[conngindex]
		return conngroupcost


from heapq import *

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		points = [tuple(point) for point in points]
		currPoint = points[0]
		vis = set()
		que = [[0, currPoint]]

		def getDist(a, b):
			return abs(a[0] - b[0]) + abs(a[1] - b[1])
		ans = 0
		while que:
			(dist, cpoint) = heappop(que)
			if cpoint in vis:
				continue
			ans += dist
			vis.add(cpoint)
			for point in points:
				if point not in vis:
					newDist = getDist(cpoint, point)
					heappush(que, [newDist, point])
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		if n <= 1:
			return 0
		minHeap = []
		for i in range(n):
			for j in range(i + 1, n):
				(x1, y1) = points[i]
				(x2, y2) = points[j]
				(dx, dy) = (abs(x1 - x2), abs(y1 - y2))
				heapq.heappush(minHeap, (dx + dy, i, j))
		uf = [i for i in range(n)]

		def find(x):
			if uf[x] == x:
				return x
			uf[x] = find(uf[x])
			return uf[x]
		res = 0
		while minHeap:
			(d, x, y) = heapq.heappop(minHeap)
			(px, py) = (find(x), find(y))
			if px == py:
				continue
			else:
				res += d
				uf[px] = py
		return res


import heapq

class UnionFind:

	def __init__(self, n):
		self.parent = {i: i for i in range(n)}
		self.rank = {i: 1 for i in range(n)}

	def add(self, x):
		self.parent[x] = x
		self.rank[x] = 0

	def find(self, x):
		if self.parent[x] != x:
			self.parent[x] = self.find(self.parent[x])
		return self.parent[x]

	def union(self, x, y):
		(xRoot, yRoot) = (self.find(x), self.find(y))
		if xRoot == yRoot:
			return
		(xRank, yRank) = (self.rank[xRoot], self.rank[yRoot])
		if xRank < yRank:
			(yRoot, xRoot) = (xRoot, yRoot)
		self.parent[yRoot] = xRoot
		self.rank[xRoot] += self.rank[yRoot]
		return

class Solution:

	def dist(self, p1, p2):
		return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		dsu = UnionFind(len(points))
		edges = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				edges.append((self.dist(points[i], points[j]), i, j))
		heapq.heapify(edges)
		ans = 0
		while edges:
			(d, u, v) = heapq.heappop(edges)
			if dsu.find(u) != dsu.find(v):
				ans += d
				dsu.union(u, v)
		return ans


class Node:

	def __init__(self, parent, value):
		self.parent = parent
		self.rank = 0
		self.size = 1
		self.value = value

class UnionFind:

	def __init__(self, nodes):
		self.subsets = [Node(i, v) for (i, v) in enumerate(nodes)]
		self.maxSubsetSize = 1

	def union(self, i, j):
		irep = self.find(i)
		jrep = self.find(j)
		if irep == jrep:
			return
		if self.subsets[irep].rank > self.subsets[jrep].rank:
			self.subsets[jrep].parent = irep
			self.subsets[irep].size += self.subsets[jrep].size
		elif self.subsets[jrep].rank > self.subsets[irep].rank:
			self.subsets[irep].parent = jrep
			self.subsets[jrep].size += self.subsets[irep].size
		else:
			self.subsets[irep].parent = jrep
			self.subsets[jrep].rank += 1
			self.subsets[jrep].size += self.subsets[irep].size
		self.maxSubsetSize = max(self.maxSubsetSize, max(self.subsets[irep].size, self.subsets[jrep].size))

	def find(self, i):
		if self.subsets[i].parent != i:
			self.subsets[i].parent = self.find(self.subsets[i].parent)
		return self.subsets[i].parent
from heapq import heapify, heappop

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []
		for i in range(len(points)):
			(x1, y1) = points[i]
			for j in range(i + 1, len(points), 1):
				(x2, y2) = points[j]
				edges.append((abs(x1 - x2) + abs(y1 - y2), i, j))
		heapify(edges)
		uf = UnionFind(range(len(points)))
		total = 0
		while len(edges) > 0:
			(d, i, j) = heappop(edges)
			if uf.find(i) != uf.find(j):
				total += d
				uf.union(i, j)
		return total


from heapq import heappop, heappush, heapify
from collections import defaultdict

def distance(pointA, pointB):
	return abs(pointA[0] - pointB[0]) + abs(pointA[1] - pointB[1])

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		mat = [[float('inf')] * n for i in range(n)]
		lookup = defaultdict(list)
		minHeap = []
		for (idx, aPoint) in enumerate(points):
			for bIdx in range(idx + 1, n):
				bPoint = points[bIdx]
				dist = distance(aPoint, bPoint)
				minHeap.append(dist)
				lookup[dist].append([idx, bIdx])
		if n == 1:
			return 0
		visited = set()
		cost = 0
		minHeap = sorted(minHeap)
		minValue = minHeap[0]
		minIndex = lookup[minValue][0]
		visited.add(minIndex[0])
		visited.add(minIndex[1])
		cost += minValue
		while len(visited) != n:
			for minValue in minHeap:
				minIndexs = lookup[minValue]
				ifFound = False
				for minIndex in minIndexs:
					x = minIndex[0]
					y = minIndex[1]
					if x in visited and y in visited:
						continue
					elif x in visited or y in visited:
						visited.add(x)
						visited.add(y)
						cost += minValue
						ifFound = True
						break
				if ifFound:
					break
		return cost


from math import inf

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def dis(i, j):
			(x1, y1, x2, y2) = (points[i][0], points[i][1], points[j][0], points[j][1])
			ans = abs(x1 - x2) + abs(y1 - y2)
			return ans
		n = len(points)
		connected = set()
		connected.add(0)
		uncon = set()
		for i in range(1, n):
			uncon.add(i)
		edges = {}
		for i in range(n):
			for j in range(n):
				if i != j:
					edges[i, j] = dis(i, j)
					edges[j, i] = edges[i, j]
		total = 0
		dis = [inf for _ in range(n)]
		pt = 0
		for _ in range(n - 1):
			for i in uncon:
				dis[i] = min(edges[i, pt], dis[i])
			(score, pt) = min(((score, i) for (i, score) in enumerate(dis)))
			dis[pt] = inf
			total += score
			connected.add(pt)
			uncon.remove(pt)
		return total


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		graph = collections.defaultdict(list)
		n = len(points)
		for i in range(n):
			for j in range(n):
				if i != j:
					graph[i].append((abs(points[j][0] - points[i][0]) + abs(points[j][1] - points[i][1]), j))
		heap = [(0, 0)]
		res = 0
		visited = set()
		while heap:
			(weight, dest) = heapq.heappop(heap)
			if dest in visited:
				continue
			res += weight
			visited.add(dest)
			for (cost, nei) in graph[dest]:
				if nei not in visited:
					heapq.heappush(heap, (cost, nei))
		return res


class order(tuple):

	def __lt__(a, b):
		return a[0] < b[0]

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		adjList = {}
		(edges, n, ans) = ([], len(points), 0)
		for i in range(n):
			for j in range(i + 1, n):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				edges.append((dist, i, j))
		parent = [i for i in range(n)]
		rank = [0 for i in range(n)]

		def find(x):
			if parent[x] != x:
				parent[x] = find(parent[x])
			return parent[x]

		def union(x, y):
			(x, y) = (find(x), find(y))
			if rank[x] > rank[y]:
				parent[y] = x
			else:
				parent[x] = y
			if rank[x] == rank[y]:
				rank[x] += 1
			return
		edges = sorted(edges, key=order)
		for (d, u, v) in edges:
			(x, y) = (find(u), find(v))
			if x != y:
				union(x, y)
				ans += d
		return ans


class UnionFind:

	def __init__(self):
		self.father = {}
		self.size = {}

	def find(self, p):
		while self.father[p] != p:
			self.father[p] = p = self.father[self.father[p]]
		return p

	def union(self, p, q):
		self.insert(p)
		self.insert(q)
		(p, q) = map(self.find, (p, q))
		if p == q:
			return False
		if self.size[p] < self.size[q]:
			(p, q) = (q, p)
		self.size[p] += self.size[q]
		self.father[q] = p
		return True

	def insert(self, p):
		if p not in self.father:
			self.father[p] = p
			self.size[p] = 1

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		dis = []
		for (i, (x, y)) in enumerate(points):
			for (u, v) in points[:i]:
				dis.append((abs(x - u) + abs(y - v), (x, y), (u, v)))
		dis.sort()
		(uf, r) = (UnionFind(), 0)
		for (d, p1, p2) in dis:
			if uf.union(p1, p2):
				r += d
		return r


from heapq import heappop, heappush, heapify

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		graph = [[] for i in range(len(points))]

		def dist(p1, p2):
			return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		start_point = 0
		min_edge = 1000000000
		for (i, p_i) in enumerate(points[:-1]):
			for (j, p_j) in enumerate(points[i + 1:], i + 1):
				d = dist(p_i, p_j)
				graph[i].append((j, d))
				graph[j].append((i, d))
				if d < min_edge:
					min_edge = d
					start_point = i
		total_dist = 0
		pq = [(d, n) for (n, d) in graph[start_point]]
		heapify(pq)
		visited = [False] * len(points)
		visited[start_point] = True
		while len(pq) > 0:
			(d, node) = heappop(pq)
			if visited[node]:
				continue
			visited[node] = True
			total_dist += d
			for (child, child_d) in graph[node]:
				if visited[child]:
					continue
				heappush(pq, (child_d, child))
		return total_dist


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		return self.MSTprim(points)

	def MSTkruskal(self, points):
		X = dict()
		R = dict()

		def make_set(point):
			X[point] = point
			R[point] = 0

		def find(point):
			if X[point] != point:
				X[point] = find(X[point])
			return X[point]

		def merge(point1, point2):
			r1 = find(point1)
			r2 = find(point2)
			if r1 != r2:
				if R[r1] > R[r2]:
					X[r2] = r1
				else:
					X[r1] = r2
					if R[r1] == R[r2]:
						R[r2] += 1

		def kruskal(graph):
			for vertex in graph['vertices']:
				make_set(vertex)
			k_tree = set()
			edges = graph['edges']
			edges.sort()
			for (weight, vertex1, vertex2) in edges:
				if find(vertex1) != find(vertex2):
					merge(vertex1, vertex2)
					k_tree.add((weight, vertex1, vertex2))
			return k_tree
		N = len(points)
		graph = {'vertices': list(range(N)), 'edges': list()}
		for i in graph['vertices']:
			for j in graph['vertices']:
				if i != j:
					graph['edges'].append((abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j))
		return sum((weight for (weight, _, _) in kruskal(graph)))

	def MSTprim(self, points):

		def prim(origin_vertex, edges):
			adjacent_vertex = defaultdict(list)
			for (weight, vertex1, vertex2) in edges:
				adjacent_vertex[vertex1].append((weight, vertex1, vertex2))
			p_tree = []
			chosed = set([origin_vertex])
			adjacent_vertexs_edges = adjacent_vertex[origin_vertex]
			heapify(adjacent_vertexs_edges)
			while adjacent_vertexs_edges:
				(weight, vertex1, vertex2) = heappop(adjacent_vertexs_edges)
				if vertex2 not in chosed:
					chosed.add(vertex2)
					p_tree.append((vertex1, vertex2, weight))
					for next_vertex in adjacent_vertex[vertex2]:
						if next_vertex[2] not in chosed:
							heappush(adjacent_vertexs_edges, next_vertex)
			return p_tree
		N = len(points)
		graph = {'vertices': list(range(N)), 'edges': list()}
		for i in graph['vertices']:
			for j in graph['vertices']:
				if i != j:
					graph['edges'].append((abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j))
		return sum((weight for (_, _, weight) in prim(graph['vertices'][0], graph['edges'])))


class DSU:

	def __init__(self, n):
		self.n = n
		self.fa = list(range(n))

	def find(self, x):
		r = x
		while self.fa[r] != r:
			r = self.fa[r]
		i = x
		while i != r:
			(i, self.fa[i]) = (self.fa[i], r)
		return r

	def join(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x != y:
			self.fa[x] = y

class Solution:

	def minCostConnectPoints(self, p: List[List[int]]) -> int:
		n = len(p)
		e = []
		for i in range(n):
			for j in range(n):
				if i == j:
					continue
				d = abs(p[i][0] - p[j][0]) + abs(p[i][1] - p[j][1])
				e.append((d, i, j))
		e.sort()
		dsu = DSU(n)
		m = 0
		ans = 0
		for (d, i, j) in e:
			if m == n - 1:
				break
			if dsu.find(i) != dsu.find(j):
				ans += d
				dsu.join(i, j)
		return ans


from heapq import *

class Solution:

	def minCostConnectPoints(self, points):
		N = len(points)
		parent = [i for i in range(N)]

		def find(v):
			while parent[v] != parent[parent[v]]:
				parent[v] = parent[parent[v]]
			return parent[v]
		dist = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		(heap, total_cost) = ([], 0)
		for u in range(N - 1):
			for v in range(u + 1, N):
				heappush(heap, [dist(points[u], points[v]), u, v])
		while heap:
			(cost, u, v) = heappop(heap)
			(pu, pv) = (find(u), find(v))
			if pu != pv:
				parent[pu] = pv
				N -= 1
				total_cost += cost
				if N == 0:
					break
		return total_cost
from heapq import *

class Solution:

	def minCostConnectPoints(self, points):
		dist = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		N = len(points)
		parent = [i for i in range(N)]

		def find(v):
			while parent[v] != parent[parent[v]]:
				parent[v] = parent[parent[v]]
			return parent[v]
		heap = []
		for i in range(N - 1):
			for j in range(i + 1, N):
				heappush(heap, (dist(points[i], points[j]), i, j))
		res = 0
		while heap:
			(d, u, v) = heappop(heap)
			(pu, pv) = (find(u), find(v))
			if pu != pv:
				parent[pu] = pv
				res += d
				N -= 1
				if N == 0:
					break
		return res

class Solution:

	def minCostConnectPoints(self, points):
		distance = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		points.sort(key=lambda p: abs(p[0]) + abs(p[1]))
		total_cost = 0
		points = [[p, distance(p, points[0])] for p in points]
		while points:
			(minIdx, mindist) = (None, float('inf'))
			for (i, (p1, dist)) in enumerate(points):
				if dist < mindist:
					(minIdx, mindist) = (i, dist)
			(p1, cost) = points.pop(minIdx)
			total_cost += cost
			for (i, (p2, dist)) in enumerate(points):
				newdist = distance(p1, p2)
				if newdist < dist:
					points[i][1] = newdist
		return total_cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def calculate_distance(x1, y1, x2, y2):
			return abs(x1 - x2) + abs(y1 - y2)
		n = len(points)
		visited = set()
		res = 0
		m = 0
		dp = [sys.maxsize for _ in range(n)]
		for i in range(n - 1):
			(x, y) = points[m]
			visited.add(m)
			for j in range(n):
				if j in visited:
					continue
				(x1, y1) = points[j]
				dp[j] = min(dp[j], calculate_distance(x, y, x1, y1))
			(v, m) = min(((j, i) for (i, j) in enumerate(dp)))
			dp[m] = sys.maxsize
			res += v
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		cnt = len(points)
		dist = []
		connected = [False] * cnt
		for i in range(cnt):
			for j in range(i):
				(p1, p2) = (points[i], points[j])
				tmp_d = abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
				dist.append([(i, j), tmp_d])
		res = 0
		dist = sorted(dist, key=lambda d: d[1])
		parent = [i for i in range(cnt)]

		def findp(x):
			if parent[x] != x:
				return findp(parent[x])
			return x

		def combine(x, y):
			(px, py) = (findp(x), findp(y))
			parent[px] = py
		for d in dist:
			if findp(d[0][0]) != findp(d[0][1]):
				combine(d[0][0], d[0][1])
				res += d[1]
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		pointSet = set()
		CostHeap = []
		for i in range(len(points)):
			pointSet.add(i)
			for j in range(i + 1, len(points)):
				heapq.heappush(CostHeap, [abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j])
		parent = defaultdict(lambda : -1)

		def find(x):
			if parent[x] == -1:
				return x
			else:
				parent[x] = find(parent[x])
				return parent[x]
		COST = 0
		while CostHeap:
			node = heapq.heappop(CostHeap)
			(cost, x, y) = node
			u = find(x)
			v = find(y)
			if u != v:
				parent[u] = v
				COST += cost
		return COST


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		total = 0
		mst = defaultdict(set)
		graph = collections.defaultdict(dict)
		visited = [False for i in range(len(points))]
		visited[0] = True
		for i in range(len(points)):
			for j in range(len(points)):
				if j == i:
					continue
				graph[i][j] = self.getDist(points[i][0], points[i][1], points[j][0], points[j][1])
		edges = [(cost, 0, to) for (to, cost) in graph[0].items()]
		heapq.heapify(edges)
		while edges:
			(cost, frm, to) = heapq.heappop(edges)
			if not visited[to]:
				visited[to] = True
				total += cost
				for (to_next, cost_next) in graph[to].items():
					if not visited[to_next]:
						heapq.heappush(edges, (cost_next, to, to_next))
		return total

	def getDist(self, x1, y1, x2, y2):
		return abs(x1 - x2) + abs(y1 - y2)


from collections import defaultdict

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		return kruskal(points)

class UnionFind:

	def __init__(self, N):
		self.par = [i for i in range(N)]
		self.rank = [0] * N

	def find(self, x):
		if self.par[x] == x:
			return x
		else:
			self.par[x] = self.find(self.par[x])
			return self.par[x]

	def union(self, x, y):
		xpar = self.find(x)
		ypar = self.find(y)
		if self.rank[xpar] > self.rank[ypar]:
			self.par[ypar] = xpar
		elif self.rank[xpar] < self.rank[ypar]:
			self.par[xpar] = ypar
		elif self.rank[xpar] == self.rank[ypar]:
			self.par[xpar] = ypar
			self.rank[xpar] += 1

	def connected(self, x, y):
		return self.find(x) == self.find(y)

def kruskal(points):
	n = len(points)
	V = UnionFind(n)
	mst = set()
	edges = set()
	for (i, (x1, y1)) in enumerate(points):
		for (j, (x2, y2)) in enumerate(points):
			edges.add((i, j, abs(x2 - x1) + abs(y2 - y1)))
	edges = sorted(edges, key=lambda e: e[2])
	cost = 0
	for e in edges:
		(i, j, w) = e
		if V.connected(i, j):
			continue
		V.union(i, j)
		mst.add(i)
		mst.add(j)
		cost += w
	return cost


from heapq import heapify, heappop, heappush

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def dist(p1, p2):
			return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		n = len(points)
		edges = []
		for i in range(n):
			for j in range(i + 1, n):
				l = dist(points[i], points[j])
				edges.append((i, j, l))

		def prim(nodes, edges):
			conn = defaultdict(list)
			for (n1, n2, c) in edges:
				conn[n1].append((c, n1, n2))
				conn[n2].append((c, n2, n1))
			mst = []
			used = set([nodes[0]])
			usable_edges = conn[nodes[0]][:]
			heapify(usable_edges)
			ans = 0
			while usable_edges:
				(cost, n1, n2) = heappop(usable_edges)
				if n2 not in used:
					used.add(n2)
					mst.append((n1, n2, cost))
					ans += cost
					for e in conn[n2]:
						if e[2] not in used:
							heappush(usable_edges, e)
			return ans
		nodes = list(range(n))
		return prim(nodes, edges)


class UnionFindGraph(dict):

	def union(self, p: Hashable, q: Hashable):
		rootOfP = self.root(p)
		rootOfQ = self.root(q)
		self[rootOfP] = rootOfQ

	def isConnected(self, p: Hashable, q: Hashable) -> bool:
		return self.root(p) == self.root(q)

	def root(self, r: Hashable) -> Hashable:
		while r != self[r]:
			self[r] = self[self[r]]
			r = self[r]
		return r

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		graph = UnionFindGraph()
		edges = []
		for (i, v) in enumerate(points):
			for (j, w) in enumerate(points[i + 1:], i + 1):
				if i != j:
					edges.append(((tuple(v), tuple(w)), self.distance(v, w)))
		edges.sort(key=lambda v: v[1])
		res = 0
		for ((a, b), distance) in edges:
			if a not in graph:
				graph[a] = a
			if b not in graph:
				graph[b] = b
			if not graph.isConnected(a, b):
				res += distance
				graph.union(a, b)
		return res

	def distance(self, a: Tuple[int, int], b: Tuple[int, int]) -> int:
		return abs(a[0] - b[0]) + abs(a[1] - b[1])


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def buildmst(graph, starting_vertex):
			mst = defaultdict(set)
			visited = set([starting_vertex])
			edges = [(cost, starting_vertex, to) for (to, cost) in list(graph[starting_vertex].items())]
			heapq.heapify(edges)
			while edges:
				(cost, frm, to) = heapq.heappop(edges)
				if to not in visited:
					visited.add(to)
					mst[frm].add(to)
					for (to_next, cost) in list(graph[to].items()):
						if to_next not in visited:
							heapq.heappush(edges, (cost, to, to_next))
			return mst
		graph = defaultdict(dict)
		for x in points:
			t = (x[0], x[1])
			for y in points:
				if x != y:
					graph[t][y[0], y[1]] = abs(x[0] - y[0]) + abs(x[1] - y[1])
		mst = dict(buildmst(graph, (points[0][0], points[0][1])))
		ans = 0
		for (k, v) in list(mst.items()):
			for p in v:
				ans += abs(k[0] - p[0]) + abs(k[1] - p[1])
		return ans


parent = 0

def find(i):
	nonlocal parent
	l1 = []
	while parent[i] != i:
		l1.append(i)
		i = parent[i]
	j = i
	for i in l1:
		parent[i] = j
	return j

def givedistance(a, b):
	return abs(a[0] - b[0]) + abs(a[1] - b[1])

class Solution:

	def minCostConnectPoints(self, l: List[List[int]]) -> int:
		nonlocal parent
		visited = {}
		l1 = []
		n = len(l)
		for i in range(n):
			for j in range(i + 1, n):
				l1.append([givedistance(l[i], l[j]), tuple(l[i]), tuple(l[j])])
		l1.sort()
		l1.reverse()
		ans = 0
		if n == 1:
			return 0
		d = {}
		ind = 0
		for i in l:
			d[tuple(i)] = ind
			ind += 1
		for i in range(len(l1)):
			l1[i][1] = d[l1[i][1]]
			l1[i][2] = d[l1[i][2]]
		parent = {}
		for i in l1:
			parent[i[1]] = i[1]
			parent[i[2]] = i[2]
		taken = 0
		while taken != n - 1:
			(curr, i, j) = l1.pop()
			p1 = find(i)
			p2 = find(j)
			if p1 != p2:
				parent[p1] = parent[p2]
				ans += curr
				taken += 1
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def find(p, u):
			if p[u] == u:
				return u
			root_u = find(p, p[u])
			p[u] = root_u
			return root_u

		def union(p, rank, root_u, root_v):
			if rank[root_u] < rank[root_v]:
				p[root_u] = root_v
			elif rank[root_v] < rank[root_u]:
				p[root_v] = root_u
			else:
				rank[root_u] += 1
				p[root_v] = root_u
		h = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				cost = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				heapq.heappush(h, [cost, i, j])
		p = list(range(len(points)))
		rank = [1] * len(points)
		total_cost = 0
		while len(h):
			(cost, u, v) = heapq.heappop(h)
			(root_u, root_v) = (find(p, u), find(p, v))
			if root_u == root_v:
				continue
			union(p, rank, root_u, root_v)
			total_cost += cost
		return total_cost


from collections import defaultdict
import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		(s, heap, c, ans) = (set(), list(), 0, 0)
		parent = [-1] * len(points)
		if len(points) == 1 or not points:
			return 0

		def give_dist(x, y):
			return abs(x[0] - y[0]) + abs(x[1] - y[1])
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				heap.append([give_dist(points[i], points[j]), i, j])
		heapq.heapify(heap)

		def find(x):
			if parent[x] == -1:
				return x
			parent[x] = find(parent[x])
			return parent[x]

		def union(x, y):
			(px, py) = (find(x), find(y))
			parent[px] = py
		while c < len(points) - 1:
			(d, x, y) = heapq.heappop(heap)
			if find(x) != find(y):
				ans += d
				union(x, y)
				c += 1
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		uf = {}

		def find(x):
			uf.setdefault(x, x)
			if uf[x] != x:
				uf[x] = find(uf[x])
			return uf[x]

		def union(x, y):
			(px, py) = (find(x), find(y))
			if px != py:
				uf[px] = py

		@lru_cache(None)
		def dist(i, j):
			(x1, y1) = points[i]
			(x2, y2) = points[j]
			return abs(x1 - x2) + abs(y1 - y2)
		hp = []
		n = len(points)
		ans = 0
		for i in range(n):
			for j in range(i + 1, n):
				heapq.heappush(hp, (dist(i, j), i, j))
		while hp:
			(d, i, j) = heapq.heappop(hp)
			if find(i) != find(j):
				ans += d
				union(i, j)
		return ans


import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def manhattanDistance(x1, y1, x2, y2):
			return abs(x1 - x2) + abs(y1 - y2)
		n = len(points)
		distsMap = {}
		for i in range(n):
			for j in range(i + 1, n):
				(x1, y1) = points[i]
				(x2, y2) = points[j]
				distsMap[i, j] = manhattanDistance(x1, y1, x2, y2)
				distsMap[j, i] = distsMap[i, j]
		result = 0
		pq = [(0, 0)]
		seen = set()
		minDists = {i: float('inf') for i in range(n)}
		while len(pq) != 0:
			(dist, i) = heapq.heappop(pq)
			if i in seen:
				continue
			seen.add(i)
			result += dist
			minDists[i] = 0
			for j in range(n):
				if j in seen:
					continue
				minDists[j] = min(minDists[j], distsMap[i, j])
				heapq.heappush(pq, (minDists[j], j))
		return result


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edge_heap = []
		cost_map = {}
		for (i, point1) in enumerate(points):
			for (j, point2) in enumerate(points):
				if point1 == point2:
					continue
				cost_map[min(i, j), max(i, j)] = abs(point1[1] - point2[1]) + abs(point1[0] - point2[0])
		forest = set([0])
		for i in range(1, len(points)):
			heapq.heappush(edge_heap, (cost_map[0, i], (0, i)))
		total_cost = 0
		while len(forest) != len(points):
			(cost, (v1, v2)) = heapq.heappop(edge_heap)
			v1_new = v1 not in forest
			v2_new = v2 not in forest
			if v1_new == v2_new:
				continue
			forest.add(v1)
			forest.add(v2)
			total_cost += cost
			v_search = v1 if v1_new else v2
			for vx in range(len(points)):
				if vx == v_search or vx in forest:
					continue
				(i, j) = (min(v_search, vx), max(v_search, vx))
				heapq.heappush(edge_heap, (cost_map[i, j], (i, j)))
		return total_cost


class DSU:

	def __init__(self, n):
		self.p = list(range(n))

	def find(self, i):
		if self.p[i] == i:
			return i
		self.p[i] = self.find(self.p[i])
		return self.p[i]

	def unite(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return False
		self.p[x] = y
		return True

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)

		def w(u, v):
			return sum((abs(points[u][i] - points[v][i]) for i in range(2)))
		edges = [(u, v, w(u, v)) for u in range(n) for v in range(n)]
		edges.sort(key=lambda x: x[-1])
		ans = 0
		dsu = DSU(n)
		return sum((cost for [u, v, cost] in edges if dsu.unite(u, v)))


from itertools import combinations
from collections import defaultdict
import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		points = [(i, *point) for (i, point) in enumerate(points)]
		edges = defaultdict(list)
		heap = []
		for ((i, xi, yi), (j, xj, yj)) in combinations(points, 2):
			dest = abs(xi - xj) + abs(yi - yj)
			edges[i].append((j, dest))
			edges[j].append((i, dest))
			heapq.heappush(heap, (dest, i, j))
		selected = set()
		answer = 0
		pending = []
		while heap:
			(dest, i, j) = heapq.heappop(heap)
			if not selected or (i in selected) ^ (j in selected):
				selected.add(i)
				selected.add(j)
				answer += dest
				while pending:
					heapq.heappush(heap, pending.pop())
			elif i not in selected and j not in selected:
				pending.append((dest, i, j))
		return answer


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		q = [(0, 0)]
		visited = set()
		G = defaultdict(list)
		for i in range(n):
			for j in range(n):
				if i != j:
					(xi, yi) = points[i]
					(xj, yj) = points[j]
					cost = abs(xi - xj) + abs(yi - yj)
					G[i].append((cost, j))
					G[j].append((cost, i))
		total = 0
		while q and len(visited) < n:
			(cost1, v1) = heappop(q)
			if v1 not in visited:
				visited.add(v1)
				total += cost1
				for (cost2, v2) in G[v1]:
					heappush(q, (cost2, v2))
		return total


from queue import PriorityQueue
from collections import defaultdict

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		parent = defaultdict(int)
		weight = defaultdict(int)

		def make_set(x: int):
			if x in parent:
				return
			parent[x] = x
			weight[x] = 1

		def find(x: int) -> int:
			if parent[x] == x:
				return parent[x]
			parent[x] = find(parent[x])
			return parent[x]

		def union_set(x: int, y: int):
			(px, py) = (find(x), find(y))
			if px == py:
				return
			if weight[px] > weight[py]:
				parent[py] = px
				weight[px] += weight[py]
			else:
				parent[px] = py
				weight[py] += weight[px]
		n = len(points)
		ls = []
		for i in range(n):
			for j in range(i + 1, n):
				(x1, y1) = points[i]
				(x2, y2) = points[j]
				ls.append([abs(x1 - x2) + abs(y1 - y2), i, j])
		ls.sort()
		cost = 0
		for (c, x, y) in ls:
			make_set(x)
			make_set(y)
			if find(x) == find(y):
				continue
			union_set(x, y)
			cost += c
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def dist(p1, p2):
			return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		res = 0
		dis = [float('inf')] * len(points)
		visited = set()
		cur = 0
		for i in range(len(points) - 1):
			visited.add(cur)
			for j in range(len(points)):
				if j not in visited:
					dis[j] = min(dis[j], dist(points[cur], points[j]))
			(d, cur) = min(((d, j) for (j, d) in enumerate(dis)))
			dis[cur] = float('inf')
			res += d
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		distance = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		from collections import defaultdict
		n = len(points)
		c = defaultdict(list)
		for i in range(n):
			for j in range(i + 1, n):
				d = distance(points[i], points[j])
				c[i].append((d, j))
				c[j].append((d, i))
		visited = [False] * n
		answer = 0
		cnt = 0
		import heapq
		heap = c[0]
		visited[0] = True
		heapq.heapify(heap)
		while heap:
			(d, j) = heapq.heappop(heap)
			if visited[j] == False:
				visited[j] = True
				answer = answer + d
				cnt += 1
				for record in c[j]:
					heapq.heappush(heap, record)
		return answer


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		res = 0
		n = len(points)
		g = collections.defaultdict(list)
		tmp = []
		vst = set()
		for i in range(n):
			for j in range(n):
				if i != j and (i, j) not in vst:
					vst.add((i, j))
					vst.add((j, i))
					dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
					tmp.append([i, j, dist])
		parents = [i for i in range(n)]
		ranks = [1] * n

		def find(u):
			while u != parents[u]:
				parents[u] = parents[parents[u]]
				u = parents[u]
			return u

		def union(u, v):
			(root_u, root_v) = (find(u), find(v))
			if root_u == root_v:
				return False
			if ranks[root_v] > ranks[root_u]:
				(root_u, root_v) = (root_v, root_u)
			parents[root_v] = root_u
			ranks[root_u] += ranks[root_v]
			return True
		tmp.sort(key=lambda x: x[2])
		ans = 0
		for (u, v, val) in tmp:
			if union(u, v):
				ans += val
		groups = len({find(x) for x in parents})
		return ans if groups == 1 else -1


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def dist(p1, p2):
			return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		ans = 0
		d = collections.defaultdict(list)
		for (i, p1) in enumerate(points):
			for (j, p2) in enumerate(points):
				if i != j:
					cost = dist(p1, p2)
					d[i].append((cost, j))
					d[j].append((cost, i))
		heap = d[0]
		heapq.heapify(heap)
		n = len(points)
		visited = [0] * n
		visited[0] = 1
		count = 1
		while heap:
			(cost, j) = heapq.heappop(heap)
			if not visited[j]:
				visited[j] = 1
				count += 1
				ans += cost
				for item in d[j]:
					heapq.heappush(heap, item)
			if count >= n:
				break
		return ans


from heapq import heappop, heappush, heapify

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		if n <= 1:
			return 0
		ds = UFind(n)
		hp = []
		for i in range(n - 1):
			for j in range(i + 1, n):
				mhd = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				hp.append((mhd, i, j))
		heapq.heapify(hp)
		ans = 0
		while ds.count > 1:
			(mhd, i, j) = heapq.heappop(hp)
			if ds.union(i, j):
				ans += mhd
		return ans

class UFind:

	def __init__(self, n):
		self.parent = list(range(n))
		self.rank = [1] * n
		self.count = n

	def find(self, x):
		if self.parent[x] != x:
			self.parent[x] = self.find(self.parent[x])
		return self.parent[x]

	def union(self, x, y):
		(x_par, y_par) = (self.find(x), self.find(y))
		if x_par == y_par:
			return False
		else:
			self.count -= 1
			if self.rank[x_par] < self.rank[y_par]:
				self.parent[x_par] = y_par
			elif self.rank[x_par] > self.rank[y_par]:
				self.parent[y_par] = x_par
			else:
				self.parent[x_par] = y_par
				self.rank[y_par] += 1
			return True


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		heap = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				(x1, y1) = points[i]
				(x2, y2) = points[j]
				dist = abs(x1 - x2) + abs(y1 - y2)
				heap.append((dist, i, j))
		heapify(heap)
		uf = UnionFind(len(points))
		res = 0
		num_edges = 0
		while heap:
			(dist, x, y) = heappop(heap)
			if uf.union(x, y):
				res += dist
				num_edges += 1
			if num_edges == len(points) - 1:
				break
		return res

class UnionFind:

	def __init__(self, n):
		self.parent = list(range(n))
		self.rank = [0] * n

	def union(self, x, y):
		root_x = self.find(x)
		root_y = self.find(y)
		if root_x == root_y:
			return False
		if self.rank[root_x] > self.rank[root_y]:
			self.parent[root_y] = root_x
		else:
			self.parent[root_x] = root_y
			if self.rank[root_x] == self.rank[root_y]:
				self.rank[root_y] += 1
		return True

	def find(self, x):
		while x != self.parent[x]:
			self.parent[x] = self.parent[self.parent[x]]
			x = self.parent[x]
		return x


import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def dist(p1, p2):
			return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		h = [(0, 0, 0)]
		seen = set()
		res = 0
		n = len(points)
		while len(seen) < n:
			(d, u, v) = heapq.heappop(h)
			if v in seen:
				continue
			seen.add(v)
			res += d
			for w in range(n):
				if w in seen or w == v:
					continue
				heapq.heappush(h, (dist(points[v], points[w]), v, w))
		return res


import heapq

def dist(i, j, points):
	return abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])

class UnionFind:

	def __init__(self, n):
		self.root = [i for i in range(n)]
		self.cnt = n

	def find(self, x):
		if self.root[x] == x:
			return x
		p = self.root[x]
		self.root[x] = self.find(p)
		return self.root[x]

	def union(self, i, j):
		(ri, rj) = (self.find(i), self.find(j))
		self.root[ri] = rj
		self.cnt -= 1

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []
		n = len(points)
		for i in range(n):
			for j in range(i + 1, n):
				edges.append((dist(i, j, points), i, j))
		heapq.heapify(edges)
		res = 0
		uf = UnionFind(n)
		while uf.cnt > 1:
			e = None
			while True:
				e = heapq.heappop(edges)
				if uf.find(e[1]) != uf.find(e[2]):
					break
			res += e[0]
			uf.union(e[1], e[2])
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def find(x):
			if parent[x] != x:
				return find(parent[x])
			return parent[x]

		def union(x, y):
			(xroot, yroot) = (find(x), find(y))
			if xroot == yroot:
				return
			parent[xroot] = yroot
		l = len(points)
		parent = [i for i in range(l)]
		dis = []
		for i in range(l):
			for j in range(i + 1, l):
				dis.append((abs(points[j][1] - points[i][1]) + abs(points[j][0] - points[i][0]), i, j))
		heapq.heapify(dis)
		count = 0
		ans = 0
		while dis:
			(temp, node1, node2) = heapq.heappop(dis)
			if find(node1) != find(node2):
				union(node1, node2)
				ans += temp
				count += 1
			if count == l - 1:
				break
		return ans


class Solution:

	def minCostConnectPoints(self, points):
		distance = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		points.sort(key=lambda p: p[0] + p[1])
		points = [[p, distance(p, points[0])] for (i, p) in enumerate(points)]
		total_cost = 0
		while points:
			(minI, minD) = (None, float('inf'))
			for (i, (p1, dist)) in enumerate(points):
				if dist < minD:
					(minI, minD) = (i, dist)
			(p1, cost) = points.pop(minI)
			total_cost += cost
			for (i, (p2, _)) in enumerate(points):
				points[i][1] = min(points[i][1], distance(p1, p2))
		return total_cost

class Solution:

	def minCostConnectPoints(self, points):
		distance = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		points.sort(key=lambda p: p[0] + p[1])
		total_cost = 0
		points = [[p, distance(p, points[0])] for p in points]
		while points:
			(minIdx, mindist) = (None, float('inf'))
			for (i, (p1, dist)) in enumerate(points):
				if dist < mindist:
					(minIdx, mindist) = (i, dist)
			(p1, cost) = points.pop(minIdx)
			total_cost += cost
			for (i, (p2, dist)) in enumerate(points):
				newdist = distance(p1, p2)
				if newdist < dist:
					points[i][1] = newdist
		return total_cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		ans = i = connected = 0
		min_d = [10 ** 7] * n
		while connected < n - 1:
			min_d[i] = float('inf')
			min_j = i
			for j in range(n):
				if min_d[j] != float('inf'):
					min_d[j] = min(min_d[j], abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]))
					min_j = j if min_d[j] < min_d[min_j] else min_j
			ans += min_d[min_j]
			i = min_j
			connected += 1
		return ans


import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def dist(p1, p2):
			return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])

		def find(i):
			if parent[i] < 0:
				return i
			parent[i] = find(parent[i])
			return parent[i]
		res = 0
		n = len(points)
		parent = [-1] * n
		rank = [0] * n
		h = []
		for u in range(n):
			for v in range(u + 1, n):
				h.append((dist(points[u], points[v]), u, v))
		heapq.heapify(h)
		while h:
			(d, u, v) = heapq.heappop(h)
			(u, v) = (find(u), find(v))
			if u != v:
				res += d
				if rank[u] > rank[v]:
					parent[u] += parent[v]
					parent[v] = u
				else:
					parent[v] += parent[u]
					parent[u] = v
					if rank[u] == rank[v]:
						rank[v] += 1
				if parent[u] == -n or parent[v] == -n:
					break
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def manhattan(p1, p2):
			return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		n = len(points)
		seen = set()
		res = 0
		pq = [(0, 0, 0)]
		while len(seen) < n:
			(w, u, v) = heapq.heappop(pq)
			if u in seen and v in seen:
				continue
			res += w
			seen.add(u)
			seen.add(v)
			for i in range(n):
				if i != v and i not in seen:
					heapq.heappush(pq, (manhattan(points[v], points[i]), v, i))
		return res


def getDistance(i, j, points):
	(x1, y1, x2, y2) = (points[i][0], points[i][1], points[j][0], points[j][1])
	return abs(y1 - y2) + abs(x1 - x2)

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		res = 0
		nextPoint = 0
		vis = set([0])
		count = 1
		disMap = {}
		while count < n:
			(minPoint, minLength) = (0, sys.maxsize)
			for i in range(n):
				if i in vis:
					continue
				l = getDistance(nextPoint, i, points)
				if i not in disMap or l < disMap[i]:
					disMap[i] = l
				if disMap[i] < minLength:
					minLength = disMap[i]
					minPoint = i
			res += minLength
			vis.add(minPoint)
			count += 1
			nextPoint = minPoint
		return res


class Solution:

	def minCostConnectPoints(self, points):
		helper = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		(points, res) = ([[p, helper(p, points[0])] for p in points], 0)
		while points:
			minI = min(list(range(len(points))), key=lambda i: points[i][1])
			(p1, cost) = points.pop(minI)
			res += cost
			for (i, (p2, _)) in enumerate(points):
				points[i][1] = min(points[i][1], helper(p1, p2))
		return res

class Solution:

	def minCostConnectPoints(self, points):
		helper = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		(N, total_cost) = (len(points), 0)
		points = [[p, helper(p, points[0])] for p in points]
		while points:
			minI = min(list(range(len(points))), key=lambda i: points[i][1])
			(p2, cost) = points.pop(minI)
			total_cost += cost
			for (i, (p1, cost)) in enumerate(points):
				points[i][1] = min(cost, helper(p1, p2))
		return total_cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		dis = [math.inf] * n
		visited = [False] * n
		ans = 0
		dis[0] = 0
		for i in range(0, n):
			(d, j) = min(((d, j) for (j, d) in enumerate(dis)))
			dis[j] = math.inf
			visited[j] = True
			ans += d
			for k in range(0, n):
				if j == k or visited[k]:
					continue
				dis[k] = min(dis[k], abs(points[j][0] - points[k][0]) + abs(points[j][1] - points[k][1]))
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def get_dist(p, q):
			return abs(p[0] - q[0]) + abs(p[1] - q[1])
		n = len(points)
		seen = set()
		dist = [math.inf] * n
		res = 0
		cur = 0
		for i in range(n - 1):
			seen.add(cur)
			for j in range(n):
				if j in seen:
					continue
				d = get_dist(points[cur], points[j])
				dist[j] = min(dist[j], d)
			(delta, cur) = min(((d, j) for (j, d) in enumerate(dist)))
			res += delta
			dist[cur] = math.inf
		return res


import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		total_cost = 0
		(x1, y1) = points.pop()
		cost_heap = []
		for (x2, y2) in points:
			heapq.heappush(cost_heap, [abs(x1 - x2) + abs(y1 - y2), x2, y2])
		while cost_heap:
			(cost, x1, y1) = heapq.heappop(cost_heap)
			total_cost += cost
			for (i, [cost, x2, y2]) in enumerate(cost_heap):
				cost_heap[i][0] = min(cost, abs(x1 - x2) + abs(y1 - y2))
			heapq.heapify(cost_heap)
		return total_cost


import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) == 1:
			return 0
		np = len(points)
		rest = set(range(np))
		cur_val = 0
		rest.remove(cur_val)

		def get_costs(rest, node):
			return [(abs(points[node][0] - points[tmp][0]) + abs(points[node][1] - points[tmp][1]), node, tmp) for tmp in rest if tmp != node]
		q = get_costs(rest, cur_val)
		heapq.heapify(q)
		cost = 0
		while len(rest) > 0:
			(dist, node1, node2) = heapq.heappop(q)
			if node2 in rest:
				cost += dist
				rest.remove(node2)
				for rsti in get_costs(rest, node2):
					heapq.heappush(q, rsti)
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		dist = {}
		n = len(points)
		queue = []
		for i in range(n):
			x = points[i]
			for j in range(i + 1, n):
				y = points[j]
				heapq.heappush(queue, (abs(x[0] - y[0]) + abs(x[1] - y[1]), i, j))
		parents = list(range(n))
		rank = [1] * n

		def find(x):
			if parents[x] != x:
				parents[x] = find(parents[x])
			return parents[x]

		def union(x, y):
			(px, py) = (find(x), find(y))
			if px == py:
				return False
			if rank[px] < rank[py]:
				(px, py) = (py, px)
			parents[py] = px
			rank[px] += rank[px] == rank[py]
			return True
		result = 0
		for _ in range(n - 1):
			while True:
				(dist, i, j) = heapq.heappop(queue)
				if union(i, j):
					result += dist
					break
		return result


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		num_points = len(points)
		mst = {0}
		mra = 0
		hep = []

		def dist(a, b):
			return abs(a[0] - b[0]) + abs(a[1] - b[1])

		def update_heap(added):
			for (i, (x, y)) in enumerate(points):
				if i not in mst:
					heapq.heappush(hep, (dist(points[added], points[i]), added, i))
		sol = 0
		while len(mst) < num_points:
			update_heap(mra)
			while hep:
				(d, x, y) = heapq.heappop(hep)
				if y not in mst:
					mst.add(y)
					mra = y
					sol += d
					break
		return sol


class Solution:

	def minCostConnectPoints(self, p: List[List[int]]) -> int:
		(edges, n, cnt, ans) = ([], len(p), 1, 0)

		def manhattan(x, y):
			return abs(p[x][0] - p[y][0]) + abs(p[x][1] - p[y][1])
		edges = [(manhattan(i, j), (i, j)) for i in range(n) for j in range(i + 1, n)]
		heapq.heapify(edges)

		def union(x, y):
			uf[find(x)] = find(y)

		def find(x):
			if x != uf[x]:
				uf[x] = find(uf[x])
			return uf[x]
		uf = list(range(n))
		while cnt < n:
			(d, (u, v)) = heapq.heappop(edges)
			if find(u) != find(v):
				ans += d
				cnt += 1
				union(u, v)
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []
		n = len(points)
		if n == 1:
			return 0
		for i in range(n - 1):
			for j in range(i + 1, n):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				edges.append((i, j, dist))
		edges.sort(key=lambda x: x[2])
		parent = [i for i in range(n)]
		cnt = 0
		ans = 0
		for e in edges:
			x = e[0]
			y = e[1]
			px = self.find(x, parent)
			py = self.find(y, parent)
			if px != py:
				parent[px] = py
				cnt += 1
				ans += e[2]
			if cnt == n - 1:
				break
		return ans

	def find(self, x, parent):
		while parent[x] != x:
			parent[x] = parent[parent[x]]
			x = parent[x]
		return x


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		seen = set()
		heap = [[0, 0]]
		cost = 0
		for _ in range(n):
			while heap and heap[0][1] in seen:
				heapq.heappop(heap)
			(dist, i) = heapq.heappop(heap)
			cost += dist
			seen.add(i)
			for j in range(n):
				if j in seen:
					continue
				dist2j = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				heapq.heappush(heap, [dist2j, j])
		return cost


import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def distance(x, y):
			dx = abs(x[0] - y[0])
			dy = abs(x[1] - y[1])
			return dx + dy
		n = len(points)
		if n == 1:
			return 0
		if n == 2:
			return distance(points[0], points[1])
		cost = 0
		curr = 0
		dist = [float('inf')] * n
		explored = set()
		explored.add(0)
		while len(explored) < n:
			x = points[curr]
			for (j, y) in enumerate(points):
				if j in explored:
					continue
				else:
					dist[j] = min(dist[j], distance(x, y))
			(min_d, curr) = min(((d, j) for (j, d) in enumerate(dist)))
			explored.add(curr)
			dist[curr] = float('inf')
			cost += min_d
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) == 1:
			return 0
		heap = []
		visited = set()
		res = 0
		cur = 0
		visited.add(0)
		while len(visited) != len(points):
			for i in range(len(points)):
				if cur == i or i in visited:
					continue
				heapq.heappush(heap, (abs(points[i][0] - points[cur][0]) + abs(points[i][1] - points[cur][1]), i))
			while True:
				(val, nxt) = heapq.heappop(heap)
				if nxt not in visited:
					visited.add(nxt)
					res += val
					cur = nxt
					break
		return res


class Solution:

	def minCostConnectPoints(self, p: List[List[int]]) -> int:

		def manhattan(x, y):
			return abs(x[0] - y[0]) + abs(x[1] - y[1])
		(cur, N, ans) = (0, len(p), 0)
		dis = [float('inf')] * N
		seen = set()
		for _ in range(N - 1):
			seen.add(cur)
			for j in range(N):
				if j in seen:
					continue
				dis[j] = min(dis[j], manhattan(p[cur], p[j]))
			(d, cur) = min(((w, k) for (k, w) in enumerate(dis)))
			dis[cur] = float('inf')
			ans += d
		return ans


class Solution:

	def minCostConnectPoints(self, A: List[List[int]]) -> int:
		inf = float('inf')
		n = len(A)
		cost_sum = 0
		nearest_points = [inf]
		for i in range(1, n):
			nearest_points.append(abs(A[i][0] - A[0][0]) + abs(A[i][1] - A[0][1]))
		for i in range(n - 1):
			mn_cost = inf
			for j in range(n):
				if nearest_points[j] < mn_cost:
					mn_cost = nearest_points[j]
					mn_cost_index = j
			cost_sum += mn_cost
			nearest_points[mn_cost_index] = inf
			for j in range(n):
				if nearest_points[j] != inf:
					nearest_points[j] = min(nearest_points[j], abs(A[mn_cost_index][0] - A[j][0]) + abs(A[mn_cost_index][1] - A[j][1]))
		return cost_sum


class Solution:

	def minCostConnectPoints(self, points) -> int:
		pq = []
		N = len(points)

		def dist(p1, p2):
			return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		p = list(range(N))
		s = [1] * N

		def find(u):
			while u != p[u]:
				p[u] = p[p[u]]
				u = p[u]
			return p[u]
		for i in range(N):
			for j in range(i + 1, N):
				heappush(pq, [dist(points[i], points[j]), i, j])
		edges = 0
		res = 0
		while edges < N - 1:
			(d, u, v) = heappop(pq)
			(pu, pv) = (find(u), find(v))
			if pu == pv:
				continue
			edges += 1
			res += d
			if s[pv] > s[pu]:
				(pu, pv) = (pv, pu)
			p[pv] = pu
			s[pu] += s[pv]
		return res


from heapq import *

class Solution:

	def minCostConnectPoints(self, points):
		n = len(points)
		dist = lambda p0, p1: abs(p1[0] - p0[0]) + abs(p1[1] - p0[1])
		q = [(0, 0)]
		visited = set()
		nodes = set(range(len(points)))
		res = 0
		while q:
			(d, u) = heappop(q)
			if u in visited:
				continue
			visited.add(u)
			res = res + d
			if len(visited) == n:
				return res
			for v in nodes:
				if v not in visited:
					w = dist(points[u], points[v])
					heappush(q, (w, v))


import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		manhattan = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		pq = []
		p1 = points[0]
		seen_idxs = {0}
		for idx in range(len(points)):
			if idx not in seen_idxs:
				p2 = points[idx]
				heapq.heappush(pq, (manhattan(p1, p2), idx))
			else:
				continue
		total_dist = 0
		while len(seen_idxs) != len(points):
			while pq[0][-1] in seen_idxs:
				heapq.heappop(pq)
			(dist, min_idx) = heapq.heappop(pq)
			total_dist += dist
			seen_idxs.add(min_idx)
			p1 = points[min_idx]
			for idx in range(len(points)):
				if idx not in seen_idxs:
					p2 = points[idx]
					heapq.heappush(pq, (manhattan(p1, p2), idx))
		return total_dist


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def dist(p1, p2):
			return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		n = len(points)
		ds = [float('inf') for _ in range(n)]
		for i in range(1, n):
			ds[i] = dist(points[0], points[i])
		ans = 0
		for i in range(1, n):
			v = ds.index(min(ds))
			ans += ds[v]
			ds[v] = float('inf')
			for i in range(n):
				if ds[i] == float('inf'):
					continue
				ds[i] = min(ds[i], dist(points[i], points[v]))
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		heap = []
		union_find = dict()
		for i in range(len(points)):
			union_find[i] = i
			for j in range(i + 1, len(points)):
				heapq.heappush(heap, (abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j))

		def find_set(node, ufo):
			if ufo[node] == node:
				return node
			else:
				return find_set(ufo[node], ufo)
		cost = 0
		n = 0
		while heap:
			currEdge = heapq.heappop(heap)
			left_root = find_set(currEdge[1], union_find)
			right_root = find_set(currEdge[2], union_find)
			if left_root != right_root:
				cost += currEdge[0]
				n += 1
				if n == len(points) - 1:
					break
				union_find[left_root] = right_root
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		res = 0
		n = len(points)
		mst = [False] * n
		dist = [None] * n
		i = 0
		dist[i] = 0
		mst[i] = True
		for _ in range(n - 1):
			min_dist = None
			next_i = None
			for j in range(n):
				if not mst[j]:
					cur_dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
					if dist[j] is None:
						dist[j] = cur_dist
					elif dist[j] > cur_dist:
						dist[j] = cur_dist
					if min_dist is None or min_dist > dist[j]:
						min_dist = dist[j]
						next_i = j
			i = next_i
			res += dist[i]
			mst[i] = True
		return res


import heapq

class UnionFind:

	def __init__(self, n):
		self.parent = list(range(n + 1))
		self.rank = [0] * (n + 1)

	def find(self, x):
		if x != self.parent[x]:
			self.parent[x] = self.find(self.parent[x])
		return self.parent[x]

	def union(self, x, y):
		px = self.find(x)
		py = self.find(y)
		if px == py:
			return False
		if self.rank[px] > self.rank[py]:
			self.parent[py] = px
		elif self.rank[px] < self.rank[py]:
			self.parent[px] = py
		else:
			self.parent[px] = py
			self.rank[px] += 1
		return True

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		l = len(points)
		if l == 1:
			return 0
		u = UnionFind(l)
		li = []
		c = 0
		ans = 0
		for i in range(l):
			for j in range(i + 1, l):
				v = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				li.append((v, i, j))
		heapq.heapify(li)
		while li:
			p = heapq.heappop(li)
			if u.find(p[1]) != u.find(p[2]):
				u.union(p[1], p[2])
				c = c + 1
				ans = ans + p[0]
			if c == l - 1:
				return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		edges = []
		for i in range(n - 1):
			for j in range(i + 1, n):
				d = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				edges.append((d, i, j))
		cost = 0
		found = 0
		parents = list(range(n))

		def find(a):
			while a != parents[a]:
				(a, parents[a]) = (parents[a], parents[parents[a]])
			return a

		def union(a, b):
			parents[find(a)] = find(b)
		for (c, a, b) in sorted(edges):
			if find(a) != find(b):
				union(a, b)
				found += 1
				cost += c
			if found == n - 1:
				break
		return cost


class DSU:

	def __init__(self, length):
		self.storage = [x for x in range(length)]
		self.rank = [0] * length

	def find(self, val):
		return self.find(self.storage[val]) if val != self.storage[val] else val

	def union(self, val1, val2):
		place_1 = self.find(val1)
		place_2 = self.find(val2)
		if self.rank[place_1] > self.rank[place_2]:
			self.storage[place_2] = self.storage[place_1]
		elif self.rank[place_2] > self.rank[place_1]:
			self.storage[place_1] = self.storage[place_2]
		else:
			self.rank[place_1] += 1
			self.storage[place_2] = self.storage[place_1]

class Solution:

	def distance(self, p1, p2):
		return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		possible_pairs = []
		n = len(points)
		for i in range(n):
			for j in range(i + 1, n):
				possible_pairs.append((i, j, self.distance(points[i], points[j])))
		possible_pairs.sort(key=lambda x: x[2])
		result = 0
		index = 0
		count = 0
		dsu = DSU(n)
		while index < len(possible_pairs) and count != n - 1:
			(f, to, d) = possible_pairs[index]
			x = dsu.find(f)
			y = dsu.find(to)
			if x != y:
				count += 1
				dsu.union(x, y)
				result += d
			index += 1
		return result


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		adj = [[inf for _ in range(n)] for _ in range(n)]
		for i in range(n):
			for j in range(i + 1, n):
				adj[i][j] = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				adj[j][i] = adj[i][j]
		selected = [False for _ in range(n)]
		min_edges = [[inf, -1] for _ in range(n)]
		min_edges[0][0] = 0
		total = 0
		for i in range(n):
			v = -1
			for j in range(n):
				if not selected[j] and (v == -1 or min_edges[j][0] < min_edges[v][0]):
					v = j
			selected[v] = True
			total += min_edges[v][0]
			for to in range(n):
				if adj[v][to] < min_edges[to][0]:
					min_edges[to][0] = adj[v][to]
		return total


import heapq

class DisjointSet:

	def __init__(self, n):
		self.parent = [i for i in range(n)]
		self.rank = [1 for _ in range(n)]

	def union(self, a, b):
		pa = self.find(a)
		pb = self.find(b)
		if pa == pb:
			return
		if self.rank[pa] > self.rank[pb]:
			self.parent[pb] = pa
			self.rank[pa] += self.rank[pb]
		else:
			self.parent[pa] = pb
			self.rank[pb] += self.rank[pa]

	def find(self, a):
		if self.parent[a] == a:
			return a
		self.parent[a] = self.find(self.parent[a])
		return self.parent[a]

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def distance(u, v):
			dx = abs(u[0] - v[0])
			dy = abs(u[1] - v[1])
			return dx + dy
		n = len(points)
		if n == 1:
			return 0
		if n == 2:
			return distance(points[0], points[1])
		cost = 0
		curr = 0
		dist = [float('inf')] * n
		explored = set()
		explored.add(0)
		cnt = 1
		while cnt < n:
			u = points[curr]
			for (j, v) in enumerate(points):
				if j in explored:
					continue
				else:
					dist[j] = min(dist[j], distance(u, v))
			(min_d, curr) = min(((d, j) for (j, d) in enumerate(dist)))
			explored.add(curr)
			cnt += 1
			dist[curr] = float('inf')
			cost += min_d
		return cost


class Solution:

	def find(self, parents, i):
		if parents[i] == -1:
			return i
		return self.find(parents, parents[i])

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		if n <= 1:
			return 0
		pairs = []
		for i in range(n):
			for j in range(i + 1, n):
				pairs.append((i, j))

		def distance(i, j):
			(p1, p2) = (points[i], points[j])
			return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		pairs = sorted(pairs, key=lambda pair: distance(pair[0], pair[1]))
		total = 0
		parents = [-1] * n
		countE = 0
		for pair in pairs:
			if countE >= n - 1:
				break
			(i, j) = pair
			pi = self.find(parents, i)
			pj = self.find(parents, j)
			if pi == pj:
				continue
			parents[pi] = pj
			total += distance(i, j)
			countE += 1
		return total


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def main(arr):
			if len(arr) < 1:
				return 0
			node = 0
			answer = 0
			n = len(arr)
			visit = set()
			global_dist = [float('inf')] * n
			while n > 1:
				(cur_x, cur_y) = arr[node]
				visit.add(node)
				for j in range(len(arr)):
					if j in visit:
						continue
					(x, y) = arr[j]
					global_dist[j] = min(global_dist[j], abs(x - cur_x) + abs(y - cur_y))
				next_node = -1
				next_dist = float('inf')
				for (idx, dist) in enumerate(global_dist):
					if dist < next_dist:
						next_dist = dist
						next_node = idx
				node = next_node
				answer += next_dist
				global_dist[next_node] = float('inf')
				n -= 1
			return answer
		return main(points)


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		graph = [[0 for _ in range(len(points))].copy() for _ in range(len(points))]
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				graph[i][j] = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				graph[j][i] = graph[i][j]
		costs = 0
		visited = set()
		keys = [sys.maxsize] * len(points)
		parent = [0] * len(points)
		keys[0] = 0

		def minkey():
			ind = -1
			m = sys.maxsize
			for i in range(len(points)):
				if i not in visited and keys[i] < m:
					m = keys[i]
					ind = i
			return ind
		for _ in range(len(points)):
			x = minkey()
			visited.add(x)
			for i in range(len(points)):
				if graph[x][i] > 0 and i not in visited and (keys[i] > graph[x][i]):
					keys[i] = graph[x][i]
					parent[i] = x
		for i in range(len(points)):
			costs += graph[i][parent[i]]
		return costs


import heapq
from collections import defaultdict

class DSU:

	def __init__(self, par):
		self.par = par
		self.rank = defaultdict(int)

	def find(self, x):
		if x != self.par[x]:
			self.par[x] = self.find(self.par[x])
		return self.par[x]

	def union(self, x, y):
		(xr, yr) = (self.find(x), self.find(y))
		if xr == yr:
			return False
		elif self.rank[xr] > self.rank[yr]:
			self.par[yr] = xr
		elif self.rank[xr] < self.rank[yr]:
			self.par[xr] = yr
		else:
			self.par[xr] = yr
			self.rank[yr] += 1
		return True

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def dist(x, y):
			return abs(x[0] - y[0]) + abs(x[1] - y[1])
		if len(points) == 1:
			return 0
		edges = []
		heapq.heapify(edges)
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				heapq.heappush(edges, (dist(points[i], points[j]), points[i], points[j]))
		par = {(x, y): (x, y) for (x, y) in points}
		dsu = DSU(par)
		total_len = 0
		count = 0
		while count < len(points) - 1:
			(d, p1, p2) = heapq.heappop(edges)
			if dsu.union(tuple(p1), tuple(p2)):
				total_len += d
				count += 1
		return total_len


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) == 1:
			return 0
		n = len(points)
		par = [i for i in range(n)]
		sze = [1] * n

		def dist(pi: List[int], pj: List[int]) -> int:
			(x, y) = pi
			(a, b) = pj
			return abs(x - a) + abs(y - b)

		def find(i: int) -> int:
			if par[i] == i:
				return i
			return find(par[i])

		def union(i: int, j: int) -> int:
			par[i] = j
			sze[j] += sze[i]
			return sze[j]
		pq = []
		for i in range(n):
			pi = points[i]
			for j in range(i + 1, n):
				pj = points[j]
				heapq.heappush(pq, (dist(pi, pj), i, j))
		ok = set()
		total = 0
		usize = 0
		while usize < len(points):
			(cost, i, j) = heapq.heappop(pq)
			(ri, rj) = (find(i), find(j))
			if ri != rj:
				usize = union(ri, rj)
				ok.add(i)
				ok.add(j)
				total += cost
		return total


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) == 1:
			return 0
		costs = []
		for i in range(len(points)):
			for k in range(i + 1, len(points)):
				(x, y) = points[i]
				(xx, yy) = points[k]
				costs.append((abs(x - xx) + abs(y - yy), i, k))
		costs.sort()
		dd = {x: x for x in range(len(points))}

		def merge(x, y, c):
			(x, y) = (find(x), find(y))
			if x != y:
				dd[x] = y
				self.ans += c
				self.groups -= 1

		def find(x):
			if dd[x] != x:
				dd[x] = find(dd[x])
			return dd[x]
		self.groups = len(points)
		self.ans = 0
		for (c, x, y) in costs:
			merge(x, y, c)
			if self.groups == 1:
				return self.ans


class UnionFind:

	def __init__(self, n):
		self.parent = list(range(n))
		self.size = [1] * n

	def find(self, i):
		if self.parent[i] != i:
			self.parent[i] = self.find(self.parent[i])
		return self.parent[i]

	def union(self, i, j):
		pi = self.find(i)
		pj = self.find(j)
		if pi != pj:
			self.parent[max(pi, pj)] = min(pi, pj)
			self.size[min(pi, pj)] += self.size[max(pi, pj)]
			self.size[max(pi, pj)] = 0

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		distances = []
		for idx0 in range(n):
			(i0, j0) = points[idx0]
			for idx1 in range(idx0 + 1, n):
				(i1, j1) = points[idx1]
				dis = abs(i0 - i1) + abs(j0 - j1)
				distances.append([dis, idx0, idx1])
		heapq.heapify(distances)
		res = 0
		uf = UnionFind(n)
		while uf.size[0] < n:
			(dis, idx0, idx1) = heapq.heappop(distances)
			if uf.find(idx0) != uf.find(idx1):
				res += dis
				uf.union(idx0, idx1)
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		costs = [[0 for _ in range(n)] for _ in range(n)]
		for i in range(n):
			for j in range(i + 1, n):
				costs[i][j] = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				costs[j][i] = costs[i][j]
		parent = [-1 for _ in range(n)]
		keyval = [-1 for _ in range(n)]
		mst = [False for _ in range(n)]
		keyval[0] = 0
		for i in range(n):
			mini = -1
			u = -1
			for j in range(n):
				if mst[j]:
					continue
				if keyval[j] == -1:
					continue
				if mini == -1:
					mini = keyval[j]
					u = j
				elif mini != -1 and mini > keyval[j]:
					mini = keyval[j]
					u = j
			mst[u] = True
			for j in range(n):
				if j != u and (not mst[j]):
					if keyval[j] == -1 or keyval[j] > costs[u][j]:
						keyval[j] = costs[u][j]
						parent[j] = u
		r = 0
		for i in range(1, n):
			r += costs[parent[i]][i]
		return r


class DSU:

	def __init__(self, n):
		self.parent = [i for i in range(n)]
		self.rank = [0 for _ in range(n)]
		self.size = n

	def find(self, x):
		if self.parent[x] != x:
			self.parent[x] = self.find(self.parent[x])
		return self.parent[x]

	def union(self, x, y):
		(xp, yp) = (self.find(x), self.find(y))
		if xp == yp:
			return False
		if self.rank[xp] < self.rank[yp]:
			self.parent[xp] = yp
		elif self.rank[xp] > self.rank[yp]:
			self.parent[yp] = xp
		else:
			self.parent[xp] = yp
			self.rank[yp] += 1
		self.size -= 1
		return True

	def getSize(self):
		return self.size

class Solution:
	import heapq

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		(heap, n) = ([], len(points))
		for i in range(n):
			for j in range(i + 1, n):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				heapq.heappush(heap, (dist, (i, j)))
		dsu = DSU(n + 1)
		(res, i, j) = (0, 0, 0)
		while heap:
			(dist, (i, j)) = heapq.heappop(heap)
			if dsu.union(i, j):
				res += dist
				if dsu.getSize() == 2:
					return res
		return 0


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def minKey(keys, mstSet):
			min_value = float('+Inf')
			for v in range(len(points)):
				if keys[v] < min_value and (not mstSet[v]):
					min_value = keys[v]
					min_index = v
			return (min_index, min_value)

		def get_distance(u, v):
			return abs(points[u][0] - points[v][0]) + abs(points[u][1] - points[v][1])
		(size, total) = (len(points), 0)
		keys = [float('+Inf')] * size
		keys[0] = 0
		mstSet = [False] * size
		for i in range(size):
			(u, min_value) = minKey(keys, mstSet)
			total += min_value
			mstSet[u] = True
			for v in range(size):
				distance = get_distance(u, v)
				if keys[v] > distance > 0 and mstSet[v] == False:
					keys[v] = distance
		return total


class Solution:

	def minCostConnectPoints(self, p: List[List[int]]) -> int:
		(cur, N, ans) = (0, len(p), 0)
		dis = [float('inf')] * N
		seen = [False] * N
		for _ in range(N - 1):
			(x, y) = p[cur]
			seen[cur] = True
			for (j, (nx, ny)) in enumerate(p):
				if seen[j]:
					continue
				dis[j] = min(dis[j], abs(nx - x) + abs(ny - y))
			(d, cur) = min(((w, k) for (k, w) in enumerate(dis)))
			dis[cur] = float('inf')
			ans += d
		return ans


class DSU:

	def __init__(self, n):
		self.parent = [i for i in range(n)]
		self.rank = [1 for i in range(n)]
		self.count = n

	def find(self, x):
		if x != self.parent[x]:
			self.parent[x] = self.find(self.parent[x])
		return self.parent[x]

	def union(self, x, y):
		px = self.find(x)
		py = self.find(y)
		if px == py:
			return False
		self.count -= 1
		if self.rank[x] > self.rank[y]:
			self.parent[py] = px
			self.rank[px] += self.rank[py]
		else:
			self.parent[px] = py
			self.rank[py] += self.rank[px]
		return True

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		edges = []
		for i in range(n):
			for j in range(i + 1, n):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				edges.append((dist, i, j))
		edges.sort()
		res = 0
		ds = DSU(n)
		for (cost, u, v) in edges:
			if ds.count == 1:
				break
			if ds.union(u, v):
				res += cost
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def find(symbol):
			if group_map.get(symbol) is None:
				group_map[symbol] = symbol
				return group_map[symbol]
			root = symbol
			while root != group_map[root]:
				root = group_map[root]
			while symbol != root:
				parent = group_map[symbol]
				group_map[symbol] = root
				symbol = parent
			return root

		def union(symbol1, symbol2):
			root1 = find(symbol1)
			root2 = find(symbol2)
			if root1 == root2:
				return
			if group_size.get(root1) is None:
				group_map[root1] = root1
				group_size[root1] = 1
			if group_size.get(root2) is None:
				group_map[root2] = root2
				group_size[root2] = 1
			if group_size[root1] < group_size[root2]:
				group_size[root2] += group_size[root1]
				group_map[root1] = root2
			else:
				group_size[root1] += group_size[root2]
				group_map[root2] = root1
		all_edges = []
		for i in range(0, len(points)):
			for j in range(i + 1, len(points)):
				all_edges.append((i, j, abs(points[j][0] - points[i][0]) + abs(points[j][1] - points[i][1])))
		all_edges.sort(key=lambda x: x[2])
		vertices = [i for i in range(0, len(points))]
		group_map = {}
		group_size = {}
		edge_count = 0
		edge_index = 0
		total_weight = 0
		while edge_count < len(points) - 1:
			(node_1, node_2, weight) = all_edges[edge_index]
			edge_index += 1
			parent_1 = find(node_1)
			parent_2 = find(node_2)
			if parent_1 != parent_2:
				edge_count += 1
				total_weight += weight
				union(parent_1, parent_2)
		return total_weight


from heapq import *

class Solution:

	def minCostConnectPoints(self, points):
		N = len(points)
		parent = [i for i in range(N)]

		def find(v):
			while parent[v] != parent[parent[v]]:
				parent[v] = parent[parent[v]]
			return parent[v]
		dist = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		(heap, total_cost) = ([], 0)
		for u in range(N - 1):
			for v in range(u + 1, N):
				heappush(heap, [dist(points[u], points[v]), u, v])
		while heap:
			(cost, u, v) = heappop(heap)
			(pu, pv) = (find(u), find(v))
			if pu != pv:
				parent[pu] = pv
				N -= 1
				total_cost += cost
				if N == 0:
					break
		return total_cost
from heapq import *

class Solution:

	def minCostConnectPoints(self, points):
		dist = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		N = len(points)
		parent = [i for i in range(N)]

		def find(v):
			while parent[v] != parent[parent[v]]:
				parent[v] = parent[parent[v]]
			return parent[v]
		heap = []
		for i in range(N - 1):
			for j in range(i + 1, N):
				heappush(heap, (dist(points[i], points[j]), i, j))
		res = 0
		while heap:
			(d, u, v) = heappop(heap)
			(pu, pv) = (find(u), find(v))
			if pu != pv:
				parent[pu] = pv
				res += d
				N -= 1
				if N == 0:
					break
		return res

class Solution:

	def minCostConnectPoints(self, points):
		manhattan = lambda a, b, x, y: abs(a - x) + abs(b - y)
		points = sorted(points, key=lambda x: abs(x[0]) + abs(x[1]))
		connected = [points[0]]
		cost = 0
		points = list([[x[0], x[1], manhattan(connected[0][0], connected[0][1], x[0], x[1])] for x in points])
		while len(connected) <= len(points):
			minidx = None
			mindist = float('inf')
			for i in range(len(points)):
				(x, y, dist) = points[i]
				if dist < mindist:
					mindist = dist
					minidx = i
			(mx, my, mdist) = points.pop(minidx)
			cost += mdist
			for i in range(len(points)):
				(x, y, dist) = points[i]
				newdist = manhattan(x, y, mx, my)
				if newdist < dist:
					points[i][2] = newdist
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		import heapq
		if len(points) == 1:
			return 0
		heap = []
		group = {i: i for i in range(len(points))}
		for i in range(len(points) - 1):
			for j in range(i + 1, len(points)):
				heap.append([abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j])
		edgeset = []
		heapq.heapify(heap)
		while len(set(group.values())) > 1:
			(weight, s, e) = heapq.heappop(heap)
			if group[s] != group[e]:
				v1 = group[s]
				v2 = group[e]
				for (key, v) in list(group.items()):
					if v == v2:
						group[key] = v1
				edgeset.append(weight)
		return sum(edgeset)


def manhattan(x, y):
	return abs(x[0] - y[0]) + abs(x[1] - y[1])

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		mstSet = set()
		(ans, n) = (0, len(points))
		queue = [(0, (0, 0))]
		while len(mstSet) < n:
			(weight, (u, v)) = heapq.heappop(queue)
			if v in mstSet:
				continue
			ans += weight
			mstSet.add(v)
			for j in range(n):
				if j not in mstSet and j != v:
					heapq.heappush(queue, (manhattan(points[j], points[v]), (v, j)))
		return ans


class Solution:

	def minCostConnectPoints(self, p: List[List[int]]) -> int:

		def manhattan(x, y):
			return abs(x[0] - y[0]) + abs(x[1] - y[1])
		(ans, n) = (0, len(p))
		seen = set()
		vertices = [(0, (0, 0))]
		while len(seen) < n:
			(d, (u, v)) = heapq.heappop(vertices)
			if u in seen and v in seen:
				continue
			ans += d
			seen.add(v)
			for j in range(n):
				if j not in seen and j != v:
					heapq.heappush(vertices, (manhattan(p[j], p[v]), (v, j)))
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		manhattan = lambda a, b, x, y: abs(a - x) + abs(b - y)
		points = sorted(points, key=lambda x: abs(x[0]) + abs(x[1]))
		connected = [points[0]]
		cost = 0
		points = list([[x[0], x[1], manhattan(connected[0][0], connected[0][1], x[0], x[1])] for x in points])
		while len(connected) <= len(points):
			minidx = None
			mindist = float('inf')
			for i in range(len(points)):
				(x, y, dist) = points[i]
				if dist < mindist:
					mindist = dist
					minidx = i
			(mx, my, mdist) = points.pop(minidx)
			cost += mdist
			for i in range(len(points)):
				(x, y, dist) = points[i]
				newdist = manhattan(x, y, mx, my)
				if newdist < dist:
					points[i][2] = newdist
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		ss = [(0, 0)]
		n = len(points)
		inc = set()
		ans = 0
		while n:
			node = heapq.heappop(ss)
			if node[1] not in inc:
				ans += node[0]
				p1 = points[node[1]]
				for i in range(len(points)):
					if i != node[1] and i not in inc:
						p2 = points[i]
						dist = abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
						heapq.heappush(ss, (dist, i))
				inc.add(node[1])
				n -= 1
		return ans


class Node:

	def __init__(self, data, rank, node):
		self.data = data
		self.rank = rank
		self.node = node
		self.parent = self

class UnionFind(object):

	def __init__(self, n):
		self._parent = [0] * n
		self._size = [1] * n
		self.count = n
		for i in range(n):
			self._parent[i] = i

	def union(self, p, q):
		rootp = self.find(p)
		rootq = self.find(q)
		if rootp == rootq:
			return False
		self.count -= 1
		if self._size[rootp] > self._size[rootq]:
			self._size[rootp] += self._size[rootq]
			self._parent[rootq] = self._parent[q] = rootp
		else:
			self._size[rootq] += self._size[rootp]
			self._parent[rootp] = self._parent[p] = rootq
		return True

	def find(self, n):
		while self._parent[n] != n:
			self._parent[n] = self._parent[self._parent[n]]
			n = self._parent[n]
		return n

	def connected(self, p, q):
		return self.find(p) == self.find(q)

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def findManhattanDistance(p1, p2):
			return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		edges = []
		N = len(points)
		for i in range(N):
			for j in range(i + 1, N):
				edges.append([i, j, findManhattanDistance(points[i], points[j])])
		edges.sort(key=lambda x: x[2])
		hashMap = {}
		for i in range(N):
			hashMap[i] = Node(i, 0, None)
		uf = UnionFind(N)
		(edge_count, costs) = (0, 0)
		for (u, v, w) in edges:
			if uf.union(u, v):
				costs += w
				edge_count += 1
			if edge_count == N - 1:
				break
		return costs


class Solution:

	def minCostConnectPoints(self, p: List[List[int]]) -> int:
		(ans, N, heap) = (0, len(p), [(0, (0, 0))])
		seen = set()
		while len(seen) < N:
			(w, (u, v)) = heapq.heappop(heap)
			if u in seen and v in seen:
				continue
			seen.add(v)
			ans += w
			for (j, (nx, ny)) in enumerate(p):
				if j not in seen and j != v:
					heapq.heappush(heap, (abs(nx - p[v][0]) + abs(ny - p[v][1]), (v, j)))
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		result = 0
		m = 0
		q = [(0, 0, 0)]
		visited = [0] * n
		dis = [10 ** 9] * n
		dis[0] = 0
		while m < n:
			(w, j, i) = heapq.heappop(q)
			if visited[i]:
				continue
			visited[i] = 1
			for j in range(n):
				if j == i or visited[j]:
					continue
				ww = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				if ww < dis[j]:
					dis[j] = ww
					heapq.heappush(q, (ww, i, j))
			m += 1
			result += w
		return result


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		dist = [[-1 for _ in points] for _ in points]
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				d = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				dist[i][j] = d
				dist[j][i] = d
		if not points or len(points) <= 1:
			return 0
		connected = [False for _ in points]
		min_cost_pq = []
		connected[0] = True
		connected_count = 1
		res = 0
		for j in range(1, len(points)):
			heapq.heappush(min_cost_pq, (dist[0][j], j))
		while connected_count < len(points):
			(d, i) = heapq.heappop(min_cost_pq)
			if connected[i]:
				continue
			res += d
			connected[i] = True
			connected_count += 1
			for j in range(len(points)):
				if not connected[j]:
					heapq.heappush(min_cost_pq, (dist[i][j], j))
		return res


import numpy as np

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		numNode = len(points)
		if numNode == 1:
			return 0
		totalCost = 0
		current = 0
		distance = [math.inf] * numNode
		explored = set()
		for i in range(numNode - 1):
			(x0, y0) = points[current]
			explored.add(current)
			for (j, (x, y)) in enumerate(points):
				if j in explored:
					continue
				distance[j] = min(distance[j], abs(x0 - x) + abs(y0 - y))
			(cost, current) = min(((c, index) for (index, c) in enumerate(distance)))
			distance[current] = math.inf
			totalCost += cost
		return totalCost


import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def manhattan(p1, p2):
			return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		(res, n) = (0, len(points))
		verticles = [(0, (0, 0))]
		visited = set()
		while len(visited) < n:
			(d, (pre, cur)) = heapq.heappop(verticles)
			if cur in visited:
				continue
			res += d
			visited.add(cur)
			for nxt in range(n):
				if nxt not in visited and nxt != cur:
					heapq.heappush(verticles, (manhattan(points[cur], points[nxt]), (cur, nxt)))
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def getCost(a, b):
			return abs(a[0] - b[0]) + abs(a[1] - b[1])
		(res, N) = (0, len(points))
		seen = set()
		vertices = [(0, (0, 0))]
		while len(seen) < N:
			(w, (u, v)) = heapq.heappop(vertices)
			if v in seen:
				continue
			res += w
			seen.add(v)
			for j in range(N):
				if j not in seen and j != v:
					heapq.heappush(vertices, (getCost(points[v], points[j]), (v, j)))
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def func(x, y):
			return abs(x[0] - y[0]) + abs(x[1] - y[1])
		ans = 0
		n = len(points)
		print(n)
		s = set()
		ver = [(0, (0, 0))]
		while len(s) < n:
			(res, (v1, v2)) = heapq.heappop(ver)
			if v1 in s and v2 in s:
				continue
			ans += res
			s.add(v2)
			for i in range(n):
				if i not in s and i != v2:
					sol = func(points[i], points[v2])
					heapq.heappush(ver, (sol, (v2, i)))
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		visited = [False] * len(points)
		count = 0
		distance = [[0] * len(points) for p in points]
		for i in range(len(points)):
			for j in range(len(points)):
				distance[i][j] = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
		cost = 0
		visited[0] = True
		n = len(points)
		close = [1 << 29] * n
		for i in range(1, n):
			close[i] = distance[0][i]
		for k in range(n - 1):
			minCost = 1 << 29
			v = None
			for i in range(n):
				if not visited[i] and minCost > close[i]:
					v = i
					minCost = close[i]
			cost += minCost
			visited[v] = True
			for i in range(n):
				if not visited[i]:
					close[i] = min(close[i], distance[v][i])
		return cost


class DisjointSet:

	def __init__(self, n):
		self.parent = [i for i in range(n)]
		self.rank = [1 for _ in range(n)]

	def union(self, a, b):
		pa = self.find(a)
		pb = self.find(b)
		if pa == pb:
			return
		if self.rank[pa] > self.rank[pb]:
			self.parent[pb] = pa
			self.rank[pa] += self.rank[pb]
		else:
			self.parent[pa] = pb
			self.rank[pb] += self.rank[pa]

	def find(self, a):
		if self.parent[a] == a:
			return a
		self.parent[a] = self.find(self.parent[a])
		return self.parent[a]

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		edges = []
		for i in range(n):
			for j in range(i + 1, n):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				edges.append((dist, i, j))
		edges.sort()
		res = 0
		ds = DisjointSet(n)
		cnt = 0
		for (cost, u, v) in edges:
			if ds.find(u) != ds.find(v):
				ds.union(u, v)
				res += cost
				cnt += 1
			if cnt == len(points) - 1:
				break
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		N = len(points)
		import heapq
		connect = list(range(N))

		def find(x):
			if connect[x] != x:
				connect[x] = find(connect[x])
			return connect[x]

		def union(x, y):
			if find(x) != find(y):
				connect[find(x)] = find(y)
		q = []
		for i in range(N):
			for j in range(i):
				w = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				q.append((w, i, j))
		q.sort()
		res = 0
		cnt = 0
		for (w, i, j) in q:
			if cnt == N - 1:
				break
			if find(i) == find(j):
				continue
			else:
				res += w
				union(i, j)
				cnt += 1
		return res


class Node:

	def __init__(self, data, rank, node):
		self.data = data
		self.rank = rank
		self.node = node

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def findManhattanDistance(p1, p2):
			return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		edges = []
		for (i, p1) in enumerate(points):
			for j in range(i + 1, len(points)):
				edges.append([i, j, findManhattanDistance(p1, points[j])])
		edges = sorted(edges, key=lambda x: x[2])
		N = len(points)
		hashMap = {}
		for i in range(N):
			node = Node(i, 0, None)
			node.parent = node
			hashMap[node.data] = node

		def Union(data1, data2):
			node1 = hashMap[data1]
			node2 = hashMap[data2]
			p1 = findSet(node1)
			p2 = findSet(node2)
			if p1 == p2:
				return False
			if p1.rank >= p2.rank:
				p1.rank = p1.rank + 1 if p1.rank == p2.rank else p1.rank
				p2.parent = p1
			else:
				p1.parent = p2
			return True

		def findSet(node):
			while node.parent != node:
				node.parent = node.parent.parent
				node = node.parent
			return node.parent
		edge_count = 0
		costs = 0
		for (u, v, w) in edges:
			if Union(u, v):
				costs += w
				edge_count += 1
			if edge_count == N - 1:
				break
		return costs


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		ans = 0
		current_point_index = 0
		visited_point_indeces = set()
		distance_list = [float('inf')] * len(points)
		for i in range(len(points) - 1):
			visited_point_indeces.add(current_point_index)
			for j in range(len(points)):
				if j in visited_point_indeces:
					continue
				(x, y) = points[current_point_index]
				(x0, y0) = points[j]
				distance_list[j] = min(distance_list[j], abs(y0 - y) + abs(x0 - x))
			distance_list[current_point_index] = float('inf')
			(delta, current_point_index) = min(([distance, index] for (index, distance) in enumerate(distance_list)))
			ans += delta
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def dis(p1, p2):
			(x1, y1) = p1
			(x2, y2) = p2
			return abs(x1 - x2) + abs(y1 - y2)
		size = len(points)
		cost = 0
		idx = list(range(size))

		def find(x):
			if x != idx[x]:
				idx[x] = find(idx[x])
			return idx[x]

		def union(x, y):
			(xx, yy) = (find(x), find(y))
			if xx == yy:
				return False
			idx[xx] = yy
			return True
		edges = []
		for i in range(size):
			for j in range(i + 1, size):
				distance = dis(points[i], points[j])
				edges.append((distance, i, j))
		edges.sort()
		for (dis, x, y) in edges:
			if union(x, y):
				cost += dis
				size -= 1
				if size == 1:
					return cost
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if not points:
			return 0
		n = len(points)
		g = [[0] * n for _ in range(n)]
		for i in range(n):
			for j in range(n):
				(x, y) = points[i]
				(xx, yy) = points[j]
				g[i][j] = g[j][i] = abs(x - xx) + abs(y - yy)
		dist = [float('inf')] * n
		dist[0] = 0
		s = set(range(n))
		heap = [(0, 0)]
		while heap:
			(d, u) = heapq.heappop(heap)
			if u not in s:
				continue
			s.remove(u)
			for v in range(n):
				if v in s and g[u][v] < dist[v]:
					dist[v] = g[u][v]
					heapq.heappush(heap, (dist[v], v))
		return sum(dist)


import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		fathers = list(range(n))
		queue = []
		for (i, p1) in enumerate(points):
			for j in range(i + 1, n):
				p2 = points[j]
				d = self.distance(p1, p2)
				heapq.heappush(queue, (d, i * n + j, i, j))

		def find(fathers, v):
			if fathers[v] != v:
				fathers[v] = find(fathers, fathers[v])
			return fathers[v]

		def union(fathers, a, b):
			rootA = find(fathers, a)
			rootB = find(fathers, b)
			if rootA != rootB:
				fathers[rootB] = rootA
		cnt = 0
		edges = 0
		while queue and edges < n - 1:
			(d, _, i, j) = heapq.heappop(queue)
			rootI = find(fathers, i)
			rootJ = find(fathers, j)
			if rootI != rootJ:
				cnt += d
				edges += 1
				union(fathers, rootI, rootJ)
		return cnt

	def distance(self, p1, p2):
		return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def find(parent, i):
			if parent[i] == i:
				return i
			return find(parent, parent[i])

		def apply_union(parent, rank, x, y):
			xroot = find(parent, x)
			yroot = find(parent, y)
			if rank[xroot] < rank[yroot]:
				parent[xroot] = yroot
			elif rank[xroot] > rank[yroot]:
				parent[yroot] = xroot
			else:
				parent[yroot] = xroot
				rank[xroot] += 1
		ans = 0
		V = len(points)
		graph = []
		for i in range(V):
			for j in range(i):
				v = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				graph.append([i, j, v])
		(i, e) = (0, 0)
		graph = sorted(graph, key=lambda item: item[2])
		parent = []
		rank = []
		for node in range(V):
			parent.append(node)
			rank.append(0)
		while e < V - 1:
			(u, v, w) = graph[i]
			i = i + 1
			x = find(parent, u)
			y = find(parent, v)
			if x != y:
				e = e + 1
				ans += w
				apply_union(parent, rank, x, y)
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		res = 0
		connected = 1
		visited = set()
		pq = list()
		i = 0
		while connected < n:
			visited.add(i)
			for j in range(n):
				if j not in visited:
					heappush(pq, (abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), j))
			(d, i) = heappop(pq)
			while i in visited:
				(d, i) = heappop(pq)
			res += d
			connected += 1
		return res


class Unifind:

	def __init__(self, n):
		self.arr = list(range(n))
		self.rank = [0] * n

	def union(self, a, b):
		a = self.find(a)
		b = self.find(b)
		if self.rank[a] < self.rank[b]:
			(a, b) = (b, a)
		if self.rank[a] == self.rank[b]:
			self.rank[a] += 1
		self.arr[b] = a

	def find(self, a):
		if self.arr[a] != a:
			self.arr[a] = self.find(self.arr[a])
		return self.arr[a]

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		manhatan = lambda i, j: -(abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]))
		edges = sorted(((manhatan(i, j), i, j) for i in range(len(points)) for j in range(i + 1, len(points))))
		uf = Unifind(len(points))
		count = 0
		cost = 0
		while count < len(points) - 1:
			(c, i, j) = edges.pop()
			if uf.find(i) != uf.find(j):
				cost -= c
				count += 1
				uf.union(i, j)
		return cost


class Solution:

	def calculateCost(self, i, j, points):
		return abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])

	def find(self, x, roots):
		if roots[x] != x:
			roots[x] = self.find(roots[x], roots)
		return roots[x]

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if not points or len(points) < 2:
			return 0
		n = len(points)
		edges = []
		for i in range(n):
			for j in range(i + 1, n):
				weight = self.calculateCost(i, j, points)
				edges.append((weight, i, j))
		edges.sort()
		roots = [i for i in range(n)]
		res = 0
		components = n
		for edge in edges:
			(weight, x, y) = edge
			root_x = self.find(x, roots)
			root_y = self.find(y, roots)
			if root_x != root_y:
				components -= 1
				res += weight
				if components == 1:
					break
				roots[root_x] = root_y
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []
		result = 0
		for i in range(1, len(points)):
			for j in range(i):
				edges.append((j, i, abs(points[j][1] - points[i][1]) + abs(points[j][0] - points[i][0])))
		edges = sorted(edges, key=lambda k: k[2])
		treeId = []
		for i in range(len(points)):
			treeId.append(i)
		for (u, v, w) in edges:
			if treeId[u] != treeId[v]:
				result += w
				oldId = treeId[u]
				newId = treeId[v]
				for k in range(len(points)):
					if treeId[k] == oldId:
						treeId[k] = newId
		return result


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		l = [[0 for i in range(n)] for j in range(n)]
		for i in range(n - 1):
			for j in range(i + 1, n):
				res = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				l[i][j] = res
				l[j][i] = res

		def minKey():
			m = sys.maxsize
			minind = 0
			for i in range(n):
				if key[i] < m and vis[i] == 0:
					m = key[i]
					minind = i
			return minind
		vis = [0] * n
		key = [sys.maxsize] * n
		key[0] = 0
		for i in range(n - 1):
			u = minKey()
			vis[u] = 1
			for v in range(n):
				if l[u][v] and vis[v] == 0 and (l[u][v] < key[v]):
					key[v] = l[u][v]
		return sum(key)


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def find_parent(parent, x):
			if parent[x] == -1:
				return x
			return find_parent(parent, parent[x])

		def union(parent, x, y):
			x_s = find_parent(parent, x)
			y_s = find_parent(parent, y)
			parent[x_s] = y_s

		def kruskals(edges):
			parent = [-1] * len(points)
			min_weight = 0
			i = 0
			j = 0
			while j < len(points) - 1:
				(start, end, weight) = edges[i]
				x = find_parent(parent, start)
				y = find_parent(parent, end)
				i += 1
				if x != y:
					j += 1
					union(parent, x, y)
					min_weight += weight
			return min_weight
		edges = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				dis = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				edges.append([i, j, dis])
		edges.sort(key=lambda x: x[2])
		return kruskals(edges)


class DisjointSet:

	def __init__(self, n):
		self.parent = [i for i in range(n)]
		self.rank = [1] * n

	def find(self, x):
		if self.parent[x] == x:
			return x
		return self.find(self.parent[x])

	def union(self, x, y):
		px = self.find(x)
		py = self.find(y)
		if self.rank[px] > self.rank[py]:
			self.parent[py] = px
			self.rank[px] += self.rank[py]
		else:
			self.parent[px] = py
			self.rank[py] += self.rank[px]

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)

		def ManhattanDistance(p1, p2):
			(x1, y1) = p1
			(x2, y2) = p2
			return abs(x2 - x1) + abs(y2 - y1)
		edges = [(ManhattanDistance(points[i], points[j]), i, j) for i in range(n) for j in range(i + 1, n)]
		edges.sort()
		graph = DisjointSet(n)
		ans = 0
		i = 0
		for (cost, u, v) in edges:
			if graph.find(u) != graph.find(v):
				graph.union(u, v)
				ans += cost
				i += 1
			if i == n - 1:
				break
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		distances = []
		for i in range(n - 1):
			for j in range(i + 1, n):
				distances.append([i, j, self.dist(points[i], points[j])])
		distances.sort(key=lambda x: x[2])
		parent = []
		for i in range(n):
			parent.append(i)
		e = 0
		i = 0
		result = 0
		while e < n - 1:
			(u, v, w) = distances[i]
			i = i + 1
			x = self.find(parent, u)
			y = self.find(parent, v)
			if x != y:
				e = e + 1
				result += w
				self.union(parent, x, y)
		return result

	def dist(self, p1, p2):
		return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])

	def find(self, parent, i):
		if parent[i] == i:
			return i
		return self.find(parent, parent[i])

	def union(self, parent, x, y):
		xroot = self.find(parent, x)
		yroot = self.find(parent, y)
		if xroot != yroot:
			parent[yroot] = xroot


import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) == 1:
			return 0

		def manhattan(x1, x2):
			return abs(x1[0] - x2[0]) + abs(x1[1] - x2[1])
		total_cost = 0
		first_chosen = points.pop()
		cost_heap = []
		for point in points:
			heapq.heappush(cost_heap, [manhattan(point, first_chosen), point])
		while cost_heap:
			(cost, new_point) = heapq.heappop(cost_heap)
			total_cost += cost
			for (i, [cost, point]) in enumerate(cost_heap):
				cost_heap[i][0] = min(cost, manhattan(point, new_point))
			cost_heap.sort()
		return total_cost


from queue import PriorityQueue

class Solution:

	def findParent(self, parents, i):
		if parents[i] is None:
			return i
		else:
			return self.findParent(parents, parents[i])

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) == 0:
			return 0
		edges = []
		req_edges = len(points) - 1
		dist = 0
		parents = [None] * len(points)
		ranks = [0] * len(points)
		for (i, p1) in enumerate(points):
			for (j, p2) in enumerate(points):
				if i < j:
					edges.append([i, j, abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])])
		edges = sorted(edges, key=lambda x: x[2])
		for edge in edges:
			parent_i = self.findParent(parents, edge[0])
			parent_j = self.findParent(parents, edge[1])
			if parent_i == parent_j:
				continue
			if ranks[parent_i] < ranks[parent_j]:
				parents[parent_i] = parent_j
			elif ranks[parent_i] > ranks[parent_j]:
				parents[parent_j] = parent_i
			else:
				parents[parent_i] = parent_j
				ranks[parent_j] += 1
			dist += edge[2]
			req_edges -= 1
			if req_edges == 0:
				break
		return dist


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		self.rank = [1 for _ in range(n)]
		self.parent = [i for i in range(n)]
		distance = []
		for i in range(n - 1):
			for j in range(i + 1, n):
				dis = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				distance.append((dis, i, j))
		distance.sort(key=lambda x: x[0])
		ans = 0
		count = 0
		for (dis, u, v) in distance:
			if self.find(u) == self.find(v):
				continue
			ans += dis
			self.union(u, v)
			count += 1
			if count == n - 1:
				break
		return ans

	def union(self, a, b):
		parenta = self.find(a)
		parentb = self.find(b)
		if parenta == parentb:
			return
		if self.rank[parenta] > self.rank[parentb]:
			self.parent[parentb] = parenta
			self.rank[parenta] += self.rank[parentb]
		else:
			self.parent[parenta] = parentb
			self.rank[parentb] += self.rank[parenta]
		return

	def find(self, a):
		if self.parent[a] == a:
			return a
		else:
			self.parent[a] = self.find(self.parent[a])
			return self.parent[a]


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def md(p1, p2):
			return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		q = [md(points[0], p) for p in points]
		res = 0
		n = len(points)
		for _ in range(n - 1):
			(d, j) = min(((d, j) for (j, d) in enumerate(q) if d > 0))
			print((d, j))
			res += d
			q = [min(q[i], md(points[i], points[j])) for i in range(n)]
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)

		def dist(i, j):
			return abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
		ds = [float('inf')] * n
		for i in range(1, n):
			ds[i] = dist(0, i)
		res = 0
		for i in range(1, n):
			cost = min(ds)
			res += cost
			j = ds.index(cost)
			ds[j] = float('inf')
			for k in range(n):
				if ds[k] == float('inf'):
					continue
				ds[k] = min(ds[k], dist(j, k))
		return res


import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		ques = []
		final = (1 << n) - 1
		for i in range(n):
			for j in range(i + 1, n):
				heapq.heappush(ques, (abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j))
		p = [i for i in range(n)]
		k = [1 for i in range(n)]
		components = n
		res = 0

		def findp(x):
			while x != p[x]:
				x = p[x]
			return x

		def union(x, y):
			if k[x] > k[y]:
				k[x] += k[y]
				p[y] = x
			else:
				k[y] += k[x]
				p[x] = y
		while components != 1:
			(dist, one, two) = heapq.heappop(ques)
			pone = findp(one)
			ptwo = findp(two)
			if pone != ptwo:
				union(pone, ptwo)
				components -= 1
				res += dist
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		if n == 1:
			return 0
		dMat = [[-1 for j in range(n)] for i in range(n)]

		def d(p1, p2):
			(a, b) = p1
			(c, d) = p2
			return abs(a - c) + abs(b - d)
		for (i, p1) in enumerate(points):
			for (j, p2) in enumerate(points):
				dMat[i][j] = d(p1, p2)
		key = [float('inf')] * n
		parent = [None] * n
		key[0] = 0
		mstSet = [False] * n
		parent[0] = -1

		def minKey():
			min = float('inf')
			for v in range(n):
				if key[v] < min and mstSet[v] == False:
					min = key[v]
					min_index = v
			return min_index
		for cout in range(n):
			u = minKey()
			mstSet[u] = True
			for v in range(n):
				if dMat[u][v] > 0 and mstSet[v] == False and (key[v] > dMat[u][v]):
					key[v] = dMat[u][v]
					parent[v] = u
		res = 0
		for v in range(n):
			if parent[v] != -1:
				u = parent[v]
				res += dMat[u][v]
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = collections.defaultdict(dict)
		n = len(points)
		for i in range(n):
			for j in range(i):
				(x1, y1) = points[i]
				(x2, y2) = points[j]
				d = abs(x1 - x2) + abs(y1 - y2)
				edges[i][j] = d
				edges[j][i] = d
		ans = 0
		visited = set([0])
		cand = []
		for j in edges[0]:
			heapq.heappush(cand, [edges[0][j], j])
		ans = 0
		while len(visited) < n:
			(d, j) = heapq.heappop(cand)
			if j not in visited:
				ans += d
				visited.add(j)
				for i in edges[j]:
					if i not in visited:
						heapq.heappush(cand, [edges[j][i], i])
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def manhattan(p1, p2):
			if p1 == p2:
				return 10 ** 10
			return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])

		def makeGraph(points):
			graph = []
			for p1 in range(len(points)):
				for p2 in range(p1):
					graph.append((p2, p1, manhattan(points[p1], points[p2])))
			return graph

		def find(subsets, p1):
			if subsets[p1][0] != p1:
				subsets[p1][0] = find(subsets, subsets[p1][0])
			return subsets[p1][0]

		def union(subsets, p1, p2):
			p1root = find(subsets, p1)
			p2root = find(subsets, p2)
			if subsets[p1root][1] > subsets[p2root][1]:
				subsets[p2root][0] = p1root
			elif subsets[p2root][1] > subsets[p1root][1]:
				subsets[p1root][0] = p2root
			else:
				subsets[p1root][1] += 1
				subsets[p2root][0] = p1root
		graph = makeGraph(points)
		edges = sorted(graph, key=lambda x: x[2])
		subsets = [[x, 0] for x in range(len(points))]
		e = 0
		i = 0
		total_cost = 0
		while e < len(points) - 1:
			(p1, p2, cost) = edges[i]
			if find(subsets, p1) != find(subsets, p2):
				union(subsets, p1, p2)
				total_cost += cost
				e += 1
			else:
				pass
			i += 1
		return total_cost


class DisjointSet:

	def __init__(self, n):
		self.rank = {i: i for i in range(n)}
		self.size = n
		self.parent = {i: i for i in range(n)}

	def find(self, i):
		if self.parent[i] != i:
			self.parent[i] = self.find(self.parent[i])
		return self.parent[i]

	def union(self, i, j):
		(root_i, root_j) = (self.find(i), self.find(j))
		if root_i == root_j:
			return False
		if self.rank[root_i] > self.rank[root_j]:
			self.parent[root_j] = root_i
		elif self.rank[root_i] < self.rank[root_j]:
			self.parent[root_i] = root_j
		else:
			self.parent[root_j] = root_i
			self.rank[root_i] += 1
		self.size -= 1
		return True

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		ds = DisjointSet(n)
		d = []
		for i in range(n):
			for j in range(i, n):
				d_ij = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				heapq.heappush(d, [d_ij, i, j])
		min_cost = 0
		while ds.size > 1:
			(d_ij, i, j) = heapq.heappop(d)
			if ds.union(i, j):
				min_cost += d_ij
		return min_cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) <= 1:
			return 0
		N = len(points)
		distances = [float('inf')] * N
		seen = set()
		ans = 0
		curr = 0
		for i in range(N - 1):
			(x1, y1) = points[curr]
			seen.add(curr)
			for j in range(N):
				(x2, y2) = points[j]
				if j in seen:
					continue
				distances[j] = min(abs(x1 - x2) + abs(y1 - y2), distances[j])
			(delta, curr) = min(((d, j) for (j, d) in enumerate(distances)))
			distances[curr] = float('inf')
			ans += delta
		return ans


import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		edges = [[] for i in range(n)]
		for i in range(n - 1):
			for j in range(i + 1, n):
				md = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				edges[i].append((md, j))
				edges[j].append((md, i))
		i = 0
		visited = set()
		visited.add(i)
		li = edges[i]
		heapq.heapify(li)
		result = 0
		while li:
			(d, j) = heapq.heappop(li)
			if j not in visited:
				visited.add(j)
				result += d
				if len(visited) == n:
					return result
				for edge in edges[j]:
					if edge[1] not in visited:
						heapq.heappush(li, edge)
		return result


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def manhattan(p1, p2):
			return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		q = []
		for i in range(1, len(points)):
			heapq.heappush(q, (manhattan(points[0], points[i]), 0, i))
		network = set([0])
		res = 0
		while q and len(network) < len(points):
			(d, prev, node) = heapq.heappop(q)
			if node in network:
				continue
			network.add(node)
			res += d
			for neigh in range(len(points)):
				if neigh not in network:
					heapq.heappush(q, (manhattan(points[neigh], points[node]), node, neigh))
		return res


from heapq import heappop, heappush, heapify

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		if len(points) == 1:
			return 0
		res = 0
		curr = 0
		dis = [math.inf] * n
		explored = set()
		for i in range(n - 1):
			(x0, y0) = points[curr]
			explored.add(curr)
			for (j, (x, y)) in enumerate(points):
				if j in explored:
					continue
				dis[j] = min(dis[j], abs(x - x0) + abs(y - y0))
			(delta, curr) = min(((d, j) for (j, d) in enumerate(dis)))
			dis[curr] = math.inf
			res += delta
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		N = len(points)
		if N <= 1:
			return 0
		edges = []
		for i in range(N):
			p1 = points[i]
			for j in range(i + 1, N):
				p2 = points[j]
				cost = abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
				edges.append((cost, i, j))
		edges.sort()
		A = set()
		B = set(range(N))
		A.add(0)
		B.discard(0)
		rtv = 0
		while len(B) > 0:
			for (idx, e) in enumerate(edges):
				(c, a, b) = e
				if a in A and b in B:
					B.discard(b)
					A.add(b)
					rtv += c
					edges.pop(idx)
					break
				elif b in A and a in B:
					B.discard(a)
					A.add(a)
					rtv += c
					edges.pop(idx)
					break
		return rtv


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		if n == 1:
			return 0
		res = 0
		curr = 0
		dis = [float('inf')] * n
		explored = set()
		for i in range(n - 1):
			(point_x, point_y) = points[curr]
			explored.add(curr)
			for (j, (x, y)) in enumerate(points):
				if j in explored:
					continue
				dis[j] = min(dis[j], abs(x - point_x) + abs(y - point_y))
			(delta, curr) = min(((d, j) for (j, d) in enumerate(dis)))
			dis[curr] = float('inf')
			res += delta
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) == 1:
			return 0
		pq = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				temp = abs(points[j][1] - points[i][1]) + abs(points[j][0] - points[i][0])
				heapq.heappush(pq, (temp, (i, j)))
		root = list(range(len(points)))

		def find(x):
			if x != root[x]:
				root[x] = find(root[x])
			return root[x]

		def union(x, y):
			(rx, ry) = (find(x), find(y))
			if rx == ry:
				return False
			root[rx] = root[ry]
			return True
		res = 0
		conn = 0
		while conn < len(points) - 1:
			(cost, xy) = heapq.heappop(pq)
			(x, y) = xy
			if union(x, y):
				res += cost
				conn += 1
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		a = points
		n = len(a)

		def d(i, j):
			return abs(a[i][0] - a[j][0]) + abs(a[i][1] - a[j][1])
		q = []
		dst = [float('inf')] * n
		vis = [False] * n

		def consider(du, u):
			if vis[u] or du >= dst[u]:
				return
			dst[u] = du
			heappush(q, (du, u))
		consider(0, 0)
		while q:
			(du, u) = heappop(q)
			if vis[u]:
				continue
			vis[u] = True
			for v in range(n):
				consider(d(u, v), v)
		return sum(dst)


from heapq import heappush, heappop

class DSU:

	def __init__(self, N):
		self.par = list(range(N))
		self.sz = [1] * N

	def find(self, x):
		if self.par[x] != x:
			self.par[x] = self.find(self.par[x])
		return self.par[x]

	def union(self, x, y):
		(xr, yr) = (self.find(x), self.find(y))
		if xr == yr:
			return False
		if self.sz[xr] < self.sz[yr]:
			(xr, yr) = (yr, xr)
		self.par[yr] = xr
		self.sz[xr] += self.sz[yr]
		self.sz[yr] = self.sz[xr]
		return True

	def size(self, x):
		return self.sz[self.find(x)]

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) == 1:
			return 0

		def weight(i, j):
			return abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
		edges = []
		ans = 0
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				heappush(edges, (weight(i, j), i, j))
		uf = DSU(len(points) + 1)
		while edges:
			e = heappop(edges)
			if uf.union(e[1], e[2]):
				ans += e[0]
				if uf.size(e[1]) == len(points):
					return ans


import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def cost(a, b):
			return abs(a[0] - b[0]) + abs(a[1] - b[1])
		points = list(map(lambda x: (x[0], x[1]), points))
		point = points[0]
		q = []
		for p in points:
			if p != point:
				heapq.heappush(q, (cost(point, p), p))
		connected = set()
		connected.add(point)
		totalCost = 0
		while len(q) > 0:
			(edgeCost, point) = heapq.heappop(q)
			if point in connected:
				continue
			connected.add(point)
			totalCost += edgeCost
			if len(connected) == len(points):
				return totalCost
			for p in points:
				if p != point:
					heapq.heappush(q, (cost(point, p), p))
		return totalCost


class Solution:

	def minCostConnectPoints(self, points):
		distance = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		points.sort(key=lambda p: p[0] + p[1])
		total_cost = 0
		points = [[p, distance(p, points[0])] for p in points]
		while points:
			(minIdx, mindist) = (None, float('inf'))
			for (i, (p1, dist)) in enumerate(points):
				if dist < mindist:
					(minIdx, mindist) = (i, dist)
			(p1, cost) = points.pop(minIdx)
			total_cost += cost
			for (i, (p2, dist)) in enumerate(points):
				points[i][1] = min(points[i][1], distance(p1, p2))
		return total_cost
from heapq import *

class Solution:

	def minCostConnectPoints(self, points):
		N = len(points)
		parent = [i for i in range(N)]

		def find(v):
			while parent[v] != parent[parent[v]]:
				parent[v] = parent[parent[v]]
			return parent[v]
		dist = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		connections = [[u, v, dist(points[u], points[v])] for u in range(N - 1) for v in range(u + 1, N)]
		connections.sort(key=lambda x: x[2])
		(total_cost, remain) = (0, N - 1)
		for (u, v, cost) in connections:
			(pu, pv) = (find(u), find(v))
			if pu != pv:
				parent[pu] = pv
				total_cost += cost
				remain -= 1
				if remain == 0:
					break
		return total_cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		es = []
		n = len(points)
		for (i, p) in enumerate(points):
			(x, y) = p
			for j in range(i + 1, n):
				pb = points[j]
				(x2, y2) = pb
				val = abs(x - x2) + abs(y - y2)
				es.append((val, i, j))
		es.sort()
		self.father = {i: i for i in range(n)}
		ans = size = 0
		for (cost, u, v) in es:
			if self.find(u) != self.find(v):
				ans += cost
				self.union(u, v)
				size += 1
			if size == n - 1:
				break
		return ans

	def find(self, a):
		path = []
		nd = a
		fa = self.father
		while fa[nd] != nd:
			path.append(nd)
			nd = fa[nd]
		root = nd
		for nd in path:
			fa[nd] = root
		return root

	def union(self, a, b):
		fa = self.father
		ra = self.find(a)
		rb = self.find(b)
		if ra != rb:
			fa[ra] = rb


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		costs = []
		for i in range(len(points) - 1):
			for j in range(i + 1, len(points)):
				cost = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				costs.append((cost, i, j))
		costs.sort(key=lambda x: x[0])
		group_label = [i for i in range(len(points))]
		result = 0
		combined = 0

		def find_group(target: int, group_label: List[int]) -> int:
			path = []
			while not target == group_label[target]:
				path.append(target)
				target = group_label[target]
			for node in path:
				group_label[node] = target
			return target

		def union_group(target: int, source: int, group_label: List[int]) -> int:
			while not source == group_label[source]:
				next_source = group_label[source]
				group_label[source] = target
				source = next_source
			group_label[source] = target
		while combined < len(points) - 1:
			(cost, target, source) = costs.pop(0)
			target_group = find_group(target, group_label)
			source_group = find_group(source, group_label)
			if not target_group == source_group:
				union_group(target_group, source, group_label)
				result += cost
				combined += 1
		return result


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def dist(u, v):
			return abs(points[u][0] - points[v][0]) + abs(points[u][1] - points[v][1])
		n = len(points)
		ret = 0
		visited = [False] * n
		visited[0] = True
		closest = [0] * n
		for i in range(1, n):
			closest[i] = dist(0, i)
		for _ in range(n - 1):
			mini = float('inf')
			node = -1
			for i in range(n):
				if not visited[i] and closest[i] < mini:
					mini = closest[i]
					node = i
			ret += mini
			visited[node] = True
			for i in range(n):
				if not visited[i]:
					closest[i] = min(closest[i], dist(i, node))
		return ret


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		if n == 1:
			return 0
		dist_arr = []
		for i in range(n - 1):
			(x1, y1) = points[i]
			for j in range(i + 1, n):
				(x2, y2) = points[j]
				dist = abs(x1 - x2) + abs(y1 - y2)
				dist_arr.append((dist, i, j))
		heapq.heapify(dist_arr)
		root = [i for i in range(n)]

		def find(n):
			if root[n] != n:
				root[n] = find(root[n])
			return root[n]

		def union(x, y):
			s1 = find(x)
			s2 = find(y)
			if s1 != s2:
				root[s2] = root[s1]
				return 1
			return 0
		res = 0
		count = 0
		while count < n - 1:
			(dist, x, y) = heapq.heappop(dist_arr)
			if union(x, y) == 1:
				res += dist
				count += 1
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		l = len(points)
		if l == 1:
			return 0
		segs = []
		for idx1 in range(l):
			for idx2 in range(idx1 + 1, l):
				dist = abs(points[idx1][0] - points[idx2][0]) + abs(points[idx1][1] - points[idx2][1])
				segs.append((idx1, idx2, dist))
		segs.sort(key=lambda x: x[2])
		parent = [x for x in range(l)]

		def getParent(idx: int) -> int:
			if parent[idx] == idx:
				return idx
			return getParent(parent[idx])
		self.f = 1

		def union(idx1: int, idx2: int, price: int) -> int:
			p1 = getParent(idx1)
			p2 = getParent(idx2)
			if p1 == p2:
				return 0
			else:
				if self.f == 0:
					parent[p2] = p1
				else:
					parent[p1] = p2
				self.f = 1 - self.f
				return price
		ans = 0
		lines = 0
		while segs and lines < l - 1:
			s = segs.pop(0)
			off = union(s[0], s[1], s[2])
			ans += off
			if off > 0:
				lines += 1
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		N = len(points)
		if N == 1:
			return 0
		edges = []
		for i in range(N):
			for j in range(i + 1, N):
				(x1, y1) = points[i]
				(x2, y2) = points[j]
				dist = abs(x1 - x2) + abs(y1 - y2)
				edges.append((dist, i, j))
		edges.sort()
		roots = [i for i in range(N)]

		def find(i):
			if roots[i] != i:
				roots[i] = find(roots[i])
			return roots[i]

		def join(i, j):
			(ri, rj) = (find(i), find(j))
			roots[ri] = rj
		i = cnt = 0
		res = 0
		while cnt < N - 1:
			(d, x, y) = edges[i]
			i += 1
			(rx, ry) = (find(x), find(y))
			if find(x) == find(y):
				continue
			join(rx, ry)
			cnt += 1
			res += d
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		manhattan = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		(n, c) = (len(points), collections.defaultdict(list))
		for i in range(n):
			for j in range(i + 1, n):
				d = manhattan(points[i], points[j])
				c[i].append((d, j))
				c[j].append((d, i))
		(cnt, ans, visited, heap) = (1, 0, [0] * n, c[0])
		visited[0] = 1
		heapq.heapify(heap)
		while heap:
			(d, j) = heapq.heappop(heap)
			if not visited[j]:
				(visited[j], cnt, ans) = (1, cnt + 1, ans + d)
				for record in c[j]:
					if not visited[record[1]]:
						heapq.heappush(heap, record)
			if cnt >= n:
				break
		return ans if cnt >= n else 0


class Solution:

	def minCostConnectPoints(self, points) -> int:
		graph = defaultdict(list)
		for i in range(len(points)):
			(x, y) = points[i]
			for j in range(len(points)):
				(x1, y1) = points[j]
				if i != j:
					graph[i].append((abs(x - x1) + abs(y - y1), j))
		start = 0
		res = 0
		visited = {start}
		min_heap = []
		for (cost, neighbor) in graph[start]:
			heapq.heappush(min_heap, (cost, neighbor))
		while len(visited) < len(points):
			(cost, next_node) = heapq.heappop(min_heap)
			if next_node not in visited:
				visited.add(next_node)
				res += cost
				for (next_cost, next_neighbor) in graph[next_node]:
					if next_neighbor not in visited:
						heapq.heappush(min_heap, (next_cost, next_neighbor))
		return res


class Solution:

	def minCostConnectPoints(self, a: List[List[int]]) -> int:
		(ans, n, vis, pq, i) = (0, len(a), set([0]), [], 0)
		rem = set(range(1, n))
		while len(vis) < n:
			for j in rem:
				heappush(pq, (abs(a[i][0] - a[j][0]) + abs(a[i][1] - a[j][1]), j))
			while pq[0][1] in vis:
				heappop(pq)
			(val, i) = heappop(pq)
			vis.add(i)
			rem.discard(i)
			ans += val
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		ind = 0
		distance = [float('inf')] * n
		visited = [False] * n
		total_cost = 0
		for cnt in range(n):
			(x0, y0) = (points[ind][0], points[ind][1])
			for i in range(n):
				if visited[i]:
					continue
				distance[i] = min(distance[i], abs(points[i][0] - x0) + abs(points[i][1] - y0))
			(dis, ind) = min(((d, i) for (i, d) in enumerate(distance)))
			visited[ind] = True
			total_cost += dis
			distance[ind] = float('inf')
		return total_cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def find(roots, x):
			if x != roots[x]:
				roots[x] = find(roots, roots[x])
			return roots[x]
		n = len(points)
		manhattan = lambda a, b: abs(a[0] - b[0]) + abs(a[1] - b[1])
		heap = []
		roots = list(range(n))
		size = [1 for i in range(n)]
		res = 0
		for i in range(n):
			for j in range(i + 1, n):
				d = manhattan(points[i], points[j])
				heap.append((d, (i, j)))
		heapq.heapify(heap)
		while heap:
			(d, (i, j)) = heapq.heappop(heap)
			root1 = find(roots, i)
			root2 = find(roots, j)
			if root1 != root2:
				res += d
				roots[root2] = root1
				size[root1] += size[root2]
				if size[root1] == n:
					break
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def dist(a, b, c, d):
			return abs(a - c) + abs(b - d)
		res = 0
		if len(points) <= 1:
			return 0
		r = 0
		visited = set()
		k = defaultdict(lambda : 999999999)
		k[tuple(points[0])] = 0
		for _ in range(len(points)):
			m = float('inf')
			cand = ()
			for point in k:
				if k[point] < m and point not in visited:
					cand = point
					m = k[point]
			visited.add(cand)
			for point in points:
				p = tuple(point)
				if p != cand and p not in visited and (dist(cand[0], cand[1], p[0], p[1]) < k[p]):
					k[p] = dist(cand[0], cand[1], p[0], p[1])
		print((k, sum(k.values())))
		return sum(k.values())


from collections import defaultdict
import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = defaultdict(list)
		for i in range(len(points)):
			for j in range(len(points)):
				if i != j:
					(parent_x, parent_y) = points[i]
					(child_x, child_y) = points[j]
					distance = abs(child_x - parent_x) + abs(child_y - parent_y)
					edges[i].append((distance, j))
		heap = [(0, 0, 0)]
		seen_points = set()
		total_distance = 0
		while len(seen_points) < len(points):
			(distance, parent_point, child_point) = heapq.heappop(heap)
			while child_point in seen_points:
				(distance, parent_point, child_point) = heapq.heappop(heap)
			seen_points.add(child_point)
			total_distance += distance
			for (distance, child_child_point) in edges[child_point]:
				if child_child_point not in seen_points:
					heapq.heappush(heap, (distance, child_point, child_child_point))
		return total_distance


class Solution:

	def minCostConnectPoints(self, a: List[List[int]]) -> int:
		n = len(a)
		if n <= 1:
			return 0
		d = defaultdict(list)
		min_val = float('inf')
		min_i = min_j = None
		for i in range(n - 1):
			for j in range(i + 1, n):
				val = abs(a[i][0] - a[j][0]) + abs(a[i][1] - a[j][1])
				d[i].append((val, i, j))
				d[j].append((val, j, i))
				if min_val > val:
					(min_val, min_i, min_j) = (val, i, j)
		for i in range(n):
			heapify(d[i])
		q = [heappop(d[i]) for i in (min_i, min_j)]
		heapify(q)
		(ans, cur) = (0, set())
		while len(cur) < n:
			(val, i, j) = heappop(q)
			if i not in cur or j not in cur:
				ans += val
			cur.add(i)
			cur.add(j)
			while d[i] and d[i][0][2] in cur:
				heappop(d[i])
			if d[i]:
				heappush(q, heappop(d[i]))
			while d[j] and d[j][0][2] in cur:
				heappop(d[j])
			if d[j]:
				heappush(q, heappop(d[j]))
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		vertices = len(points)
		self.V = vertices
		self.graph = [[0 for column in range(vertices)] for row in range(vertices)]
		for i in range(self.V):
			for j in range(self.V):
				if i == j:
					self.graph[i][j] = 0
				else:
					self.graph[i][j] = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
		return self.primMST()

	def minKey(self, key, mstSet):
		min = math.inf
		for v in range(self.V):
			if key[v] < min and mstSet[v] == False:
				min = key[v]
				min_index = v
		return min_index

	def primMST(self):
		key = [math.inf] * self.V
		parent = [None] * self.V
		key[0] = 0
		mstSet = [False] * self.V
		parent[0] = -1
		for cout in range(self.V):
			u = self.minKey(key, mstSet)
			mstSet[u] = True
			for v in range(self.V):
				if self.graph[u][v] > 0 and mstSet[v] == False and (key[v] > self.graph[u][v]):
					key[v] = self.graph[u][v]
					parent[v] = u
		res = 0
		for i in range(1, self.V):
			res += self.graph[i][parent[i]]
		return res


class Solution:

	def minCostConnectPoints(self, p: List[List[int]]) -> int:
		(ans, ct, n) = (0, 0, len(p))
		seen = set()
		vertices = [(0, (0, 0))]
		manhattan = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		while ct < n:
			(w, (u, v)) = heapq.heappop(vertices)
			if u in seen and v in seen:
				continue
			ans += w
			seen.add(v)
			ct += 1
			for j in range(n):
				if j not in seen and j != v:
					heapq.heappush(vertices, (manhattan(p[j], p[v]), (v, j)))
		return ans


import heapq

def man_dist_4(x, y, u, v):
	return abs(x - u) + abs(y - v)

def man_dist_pt(ptA, ptB):
	return abs(ptA[0] - ptB[0]) + abs(ptA[1] - ptB[1])

class Solution:

	def minCostConnectPoints(self, p: List[List[int]]) -> int:

		def manhattan(x, y):
			return abs(x[0] - y[0]) + abs(x[1] - y[1])
		(ans, n) = (0, len(p))
		seen = set()
		vertices = [(0, (0, 0))]
		while len(seen) < n:
			(w, (u, v)) = heapq.heappop(vertices)
			if u in seen and v in seen:
				continue
			ans += w
			seen.add(v)
			for j in range(n):
				if j not in seen and j != v:
					heapq.heappush(vertices, (manhattan(p[j], p[v]), (v, j)))
		return ans

class SolutionTle:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) < 2:
			return 0
		points.sort()
		lost = {(x, y) for (x, y) in points}
		found = set()
		(x, y) = lost.pop()
		found.add((x, y))
		minc = float('inf')
		for (u, v) in lost:
			md = man_dist_4(x, y, u, v)
			if minc > md:
				minc = md
				minu = u
				minv = v
		cost = minc
		lost.remove((minu, minv))
		found.add((minu, minv))
		while lost:
			minc = float('inf')
			for (x, y) in found:
				for (u, v) in lost:
					md = man_dist_4(x, y, u, v)
					if minc > md:
						minc = md
						minu = u
						minv = v
			cost += minc
			lost.remove((minu, minv))
			found.add((minu, minv))
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []
		for i in range(len(points) - 1):
			for j in range(i + 1, len(points)):
				edges.append((i, j, abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])))
		edges.sort(key=lambda x: x[2])
		seen = dict()
		ct = 0
		ans = 0
		for i in range(len(edges)):
			edge = edges[i]
			if edge[0] not in seen or edge[1] not in seen:
				if edge[0] not in seen and edge[1] not in seen:
					seen[edge[0]] = ct
					seen[edge[1]] = ct
					ct += 1
				if edge[0] not in seen and edge[1] in seen:
					seen[edge[0]] = seen[edge[1]]
				if edge[0] in seen and edge[1] not in seen:
					seen[edge[1]] = seen[edge[0]]
				ans += edge[2]
			if edge[0] not in seen and edge[1] in seen:
				seen[edge[0]] = seen[edge[1]]
				ans += edge[2]
			if edge[1] not in seen and edge[0] in seen:
				seen[edge[1]] = seen[edge[0]]
				ans += edge[2]
			if edge[0] in seen and edge[1] in seen:
				if seen[edge[0]] != seen[edge[1]]:
					for key in seen:
						if key != edge[1] and seen[key] == seen[edge[1]]:
							seen[key] = seen[edge[0]]
					seen[edge[1]] = seen[edge[0]]
					ans += edge[2]
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		dist = [[0] * n for _ in range(n)]
		res = 0
		for i in range(n):
			p = points[i]
			for j in range(n):
				nei = points[j]
				dist[i][j] = abs(p[0] - nei[0]) + abs(p[1] - nei[1])
		res = self.prim(n, dist, 0)
		return res

	def prim(self, n, dist, start):
		visited = set()
		res = 0
		nei = [[0, 0, 0]]
		heapq.heapify(nei)
		while len(visited) != n:
			(weight, current, dummy) = heapq.heappop(nei)
			if current in visited:
				continue
			res += weight
			visited.add(current)
			for i in range(n):
				if i not in visited:
					heapq.heappush(nei, [dist[current][i], i, i])
		return res


class Node:

	def __init__(self, data, rank, node):
		self.data = data
		self.rank = rank
		self.node = node
		self.parent = self

class Solution:

	def minCostConnectPoints(self, a: List[List[int]]) -> int:
		n = len(a)
		if n <= 1:
			return 0
		d = defaultdict(list)
		(min_val, min_i) = (float('inf'), None)
		for i in range(n - 1):
			for j in range(i + 1, n):
				val = abs(a[i][0] - a[j][0]) + abs(a[i][1] - a[j][1])
				d[i].append((val, i, j))
				d[j].append((val, j, i))
				if min_val > val:
					(min_val, min_i) = (val, i)
		for i in range(n):
			heapify(d[i])
		q = [heappop(d[min_i])]
		heapify(q)
		(ans, cur) = (0, set([min_i]))
		while len(cur) < n:
			(val, i, j) = heappop(q)
			if j not in cur:
				ans += val
			cur.add(j)
			while d[i] and d[i][0][2] in cur:
				heappop(d[i])
			if d[i]:
				heappush(q, heappop(d[i]))
			while d[j] and d[j][0][2] in cur:
				heappop(d[j])
			if d[j]:
				heappush(q, heappop(d[j]))
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		s = [0]
		res = 0
		d = {i: abs(points[i][0] - points[0][0]) + abs(points[i][1] - points[0][1]) for i in range(len(points))}
		current = 0
		while len(s) < len(points):
			min_ = float('inf')
			next_ = current
			for i in range(1, len(points)):
				if d[i] == 0:
					continue
				else:
					dis = abs(points[i][0] - points[next_][0]) + abs(points[i][1] - points[next_][1])
					if dis <= d[i]:
						d[i] = dis
					if d[i] <= min_:
						min_ = d[i]
						current = i
			res += min_
			d[current] = 0
			s.append(current)
		return res


from collections import defaultdict

class Graph:

	def __init__(self, vertices):
		self.V = vertices
		self.graph = []

	def addEdge(self, u, v, w):
		self.graph.append([u, v, w])

	def find(self, parent, i):
		if parent[i] == i:
			return i
		return self.find(parent, parent[i])

	def union(self, parent, rank, x, y):
		xroot = self.find(parent, x)
		yroot = self.find(parent, y)
		if rank[xroot] < rank[yroot]:
			parent[xroot] = yroot
		elif rank[xroot] > rank[yroot]:
			parent[yroot] = xroot
		else:
			parent[yroot] = xroot
			rank[xroot] += 1

	def KruskalMST(self):
		result = []
		i = 0
		e = 0
		self.graph = sorted(self.graph, key=lambda item: item[2])
		parent = []
		rank = []
		for node in range(self.V):
			parent.append(node)
			rank.append(0)
		while e < self.V - 1:
			(u, v, w) = self.graph[i]
			i = i + 1
			x = self.find(parent, u)
			y = self.find(parent, v)
			if x != y:
				e = e + 1
				result.append([u, v, w])
				self.union(parent, rank, x, y)
		ans = 0
		for (u, v, weight) in result:
			ans += weight
		return ans

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def getCost(x1, x2, y1, y2):
			return abs(x2 - x1) + abs(y2 - y1)
		g = Graph(len(points))
		for i in range(len(points) - 1):
			for j in range(i + 1, len(points)):
				g.addEdge(i, j, getCost(points[i][0], points[j][0], points[i][1], points[j][1]))
		return g.KruskalMST()


class Solution:

	def dist(self, x1, y1, x2, y2):
		return abs(x1 - x2) + abs(y1 - y2)

	def dist_from_point_to_all(self, points, i, n):
		return [self.dist(*points[i], *points[j]) for j in range(n)]

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		all_ = set(range(n))
		s = set([0])
		tot = 0
		dist = self.dist_from_point_to_all(points, 0, n)
		for _ in range(n - 1):
			min_dist = 10 ** 8
			for i in range(n):
				if i not in s and dist[i] < min_dist:
					pos_best = i
					min_dist = dist[i]
			tot += min_dist
			s.add(pos_best)
			dist_pos_best = self.dist_from_point_to_all(points, pos_best, n)
			dist = [min(dist[j], dist_pos_best[j]) for j in range(n)]
		return tot


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		if n == 1:
			return 0
		dic = {}
		for i in range(n - 1):
			(x1, y1) = points[i]
			for j in range(i + 1, n):
				(x2, y2) = points[j]
				dist = abs(x1 - x2) + abs(y1 - y2)
				dic[i, j] = dist
		root = [i for i in range(n)]

		def find(n):
			if root[n] != n:
				root[n] = find(root[n])
			return root[n]

		def union(x, y):
			s1 = find(x)
			s2 = find(y)
			if s1 != s2:
				root[s2] = root[s1]
				return 1
			return 0
		dic_sorted = sorted(list(dic.items()), key=lambda x: x[1])
		res = 0
		count = 0
		for item in dic_sorted:
			(x, y) = item[0]
			dist = item[1]
			if union(x, y) == 1:
				res += dist
				count += 1
			if count == n - 1:
				return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def manhattan_distance(point_1, point_2):
			(x1, y1) = point_1
			(x2, y2) = point_2
			return abs(x2 - x1) + abs(y2 - y1)
		n = len(points)
		graph = collections.defaultdict(list)
		for i in range(n):
			for j in range(i + 1, n):
				dist = manhattan_distance(points[i], points[j])
				graph[i].append((dist, j))
				graph[j].append((dist, i))
		visited = set()
		visited.add(0)
		heap = [_ for _ in graph[0]]
		heapq.heapify(heap)
		cost = 0
		while heap and len(visited) != len(points):
			(dist, neighbor) = heapq.heappop(heap)
			if neighbor not in visited:
				visited.add(neighbor)
				cost += dist
				for (new_dist, new_neighbor) in graph[neighbor]:
					if new_neighbor not in visited:
						heapq.heappush(heap, (new_dist, new_neighbor))
		return cost


from heapq import heappop, heappush

class DSU:

	def __init__(self, n):
		self.p = [i for i in range(n)]
		self.rank = [1] * n
		self.parts = n

	def find(self, a):
		if self.p[a] == a:
			return a
		self.p[a] = self.find(self.p[a])
		return self.p[a]

	def is_connected(self, a, b):
		return self.find(a) == self.find(b)

	def union(self, a, b):
		A = self.find(a)
		B = self.find(b)
		if self.rank[A] >= self.rank[B]:
			self.p[B] = A
			self.rank[A] += self.rank[B]
		else:
			self.p[A] = B
			self.rank[B] += self.rank[A]
		return

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		N = len(points)
		dsu = DSU(N)
		pq = []
		for i in range(N):
			(x1, y1) = points[i]
			for j in range(i + 1, N):
				(x2, y2) = points[j]
				heappush(pq, (abs(x1 - x2) + abs(y1 - y2), i, j))
		cost = 0
		while dsu.parts > 1:
			(c, p1, p2) = heappop(pq)
			if dsu.is_connected(p1, p2) == True:
				continue
			dsu.union(p1, p2)
			dsu.parts -= 1
			cost += c
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def dist(p1, p2):
			(x1, y1) = p1
			(x2, y2) = p2
			return abs(x1 - x2) + abs(y1 - y2)
		n = len(points)
		d = [float('inf')] * n
		cur = 0
		ans = 0
		seen = set()
		for i in range(n - 1):
			seen.add(cur)
			for (j, p) in enumerate(points):
				if j in seen:
					continue
				d[j] = min(d[j], dist(points[cur], points[j]))
			(min_d, nxt) = min(((d, j) for (j, d) in enumerate(d)))
			d[nxt] = float('inf')
			cur = nxt
			ans += min_d
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		L = len(points)
		res = 0
		con = {}
		father = {i: i for i in range(L)}

		def find(pidx):
			if father[pidx] == pidx:
				return pidx
			return find(father[pidx])

		def union(p, q):
			if p != q:
				if p < q:
					father[q] = p
				else:
					father[p] = q
		for (i, p) in enumerate(points):
			for (j, p2) in enumerate(points):
				if i != j and (j, i) not in list(con.keys()):
					d = self.dis(p, p2)
					con[i, j] = d
		k = sorted(con, key=lambda x: con[x])
		count = 0
		for e in k:
			(x, y) = (e[0], e[1])
			(fx, fy) = (find(x), find(y))
			if fx != fy:
				union(fx, fy)
				count += 1
				res += con[e]
			if count == L - 1:
				break
		return res

	def dis(self, p, x):
		d = abs(x[1] - p[1]) + abs(x[0] - p[0])
		return d


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def find(i):
			if parent[i] == i:
				return i
			return find(parent[i])

		def union(p1, p2):
			if size[p1] > size[p2]:
				(p1, p2) = (p2, p1)
			parent[p1] = p2
			size[p2] += size[p1]
		if len(points) <= 1:
			return 0
		dist = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				d = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				dist.append((d, i, j))
		dist.sort()
		edge = 0
		res = 0
		parent = list(range(len(points)))
		size = [1] * len(points)
		for (d, n1, n2) in dist:
			(p1, p2) = (find(n1), find(n2))
			if p1 == p2:
				continue
			res += d
			union(p1, p2)
			edge += 1
			if edge == len(points) - 1:
				return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		edges = []

		def distance(point1, points):
			return abs(point1[0] - point2[0]) + abs(point1[1] - point2[1])
		for (i, point1) in enumerate(points):
			for (j, point2) in enumerate(points[i + 1:]):
				edges.append((i, j + i + 1, distance(point1, point2)))
		edges = sorted(edges, key=lambda x: -x[2])
		union = list(range(n))
		rank = [1] * n

		def find(x):
			if union[x] != x:
				union[x] = find(union[x])
			return union[x]

		def connect(x, y):
			(xr, yr) = (find(x), find(y))
			if rank[xr] > rank[yr]:
				union[yr] = xr
				rank[xr] += rank[yr]
			else:
				union[xr] = yr
				rank[yr] += rank[xr]
		result = 0
		times = 0
		while edges and times < n - 1:
			(p1, p2, dis) = edges.pop()
			if find(p1) != find(p2):
				connect(p1, p2)
				result += dis
				times += 1
		print(rank)
		return result


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) == 1:
			return 0
		n = len(points)
		heap = []
		dic = collections.defaultdict(list)
		for i in range(n):
			for j in range(i + 1, n):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				dic[i].append((dist, j))
				dic[j].append((dist, i))
		(res, count, visited, heap) = (0, 0, [0] * n, dic[0])
		visited[0] = 1
		heapq.heapify(heap)
		while heap:
			(dist, i) = heapq.heappop(heap)
			if not visited[i]:
				res += dist
				count += 1
				visited[i] = 1
				if count == n - 1:
					return res
				for record in dic[i]:
					heapq.heappush(heap, record)


from collections import defaultdict
import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		dist = defaultdict(lambda : defaultdict(int))
		n = len(points)
		if n <= 1:
			return 0
		if n == 2:
			return abs(points[0][0] - points[1][0]) + abs(points[0][1] - points[1][1])
		for i in range(n - 1):
			for j in range(i + 1, n):
				dist[j][i] = dist[i][j] = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
		seen = set()
		start = 0
		seen.add(start)
		heap = []
		for (k, v) in list(dist[start].items()):
			heapq.heappush(heap, (v, k))
		ans = 0
		while heap:
			if len(seen) == len(points):
				return ans
			(d, node) = heapq.heappop(heap)
			if node not in seen:
				seen.add(node)
				ans += d
				for (k, v) in list(dist[node].items()):
					heapq.heappush(heap, (v, k))


from collections import Counter, defaultdict, OrderedDict, deque
from bisect import bisect_left, bisect_right
from functools import reduce, lru_cache
from typing import List
import itertools
import math
import heapq
import string
true = True
false = False
(MIN, MAX, MOD) = (-1061109567, 1061109567, 1000000007)

class Solution:

	def minCostConnectPoints(self, ps: List[List[int]]) -> int:
		n = len(ps)
		if n < 2:
			return 0
		(keys, visited) = ([MAX] * n, [False] * n)
		keys[0] = 0
		cost = 0
		for _ in range(n):
			(idx, n_min) = (0, MAX)
			for j in range(n):
				if not visited[j] and keys[j] < n_min:
					(idx, n_min) = (j, keys[j])
			visited[idx] = True
			cost += n_min
			for j in range(n):
				if not visited[j]:
					weight = abs(ps[idx][0] - ps[j][0]) + abs(ps[idx][1] - ps[j][1])
					if weight < keys[j]:
						keys[j] = weight
		return cost
sol = Solution()
points = [[0, 0], [2, 2], [3, 10], [5, 2], [7, 0]]


class Solution:

	def minCostConnectPoints(self, points):
		N = len(points)
		dist = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		connections = [[u, v, dist(points[u], points[v])] for u in range(N - 1) for v in range(u + 1, N)]
		connections.sort(key=lambda x: x[2])
		(parent, cnt, res) = ([i for i in range(N + 1)], N - 1, 0)

		def find(v):
			while parent[v] != parent[parent[v]]:
				parent[v] = parent[parent[v]]
			return parent[v]
		for (u, v, cost) in connections:
			(pu, pv) = (find(u), find(v))
			if pu != pv:
				parent[pu] = pv
				cnt -= 1
				res += cost
				if cnt == 0:
					break
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		distance = lambda u, v: abs(points[u][0] - points[v][0]) + abs(points[u][1] - points[v][1])
		graph = defaultdict(list)
		for u in range(n):
			for v in range(u + 1, n):
				dist = distance(u, v)
				graph[u].append((dist, v))
				graph[v].append((dist, u))
		count = 1
		cost = 0
		visited = [True] + [False] * (n - 1)
		heap = graph[0][:]
		heapify(heap)
		while heap:
			(dist, u) = heappop(heap)
			if not visited[u]:
				visited[u] = True
				count += 1
				cost += dist
				for link in graph[u]:
					heappush(heap, link)
			if count >= n:
				break
		return cost


from heapq import *

class Solution:

	def minCostConnectPoints(self, A: List[List[int]]) -> int:
		manhattan = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		(n, g) = (len(A), collections.defaultdict(list))
		for i in range(n):
			for j in range(i + 1, n):
				d = manhattan(A[i], A[j])
				g[i].append((d, j))
				g[j].append((d, i))
		(cnt, ans, seen, q) = (1, 0, [0] * n, g[0])
		seen[0] = 1
		heapify(q)
		while q:
			(d, k) = heappop(q)
			if seen[k]:
				continue
			(seen[k], ans, cnt) = (1, ans + d, cnt + 1)
			for r in g[k]:
				heappush(q, r)
			if cnt >= n:
				break
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def getDist(p1, p2):
			(xi, yi) = p1
			(xj, yj) = p2
			return abs(xi - xj) + abs(yi - yj)
		graph = collections.defaultdict(list)
		for i in range(len(points)):
			for j in range(len(points)):
				graph[i].append((getDist(points[i], points[j]), j))
		start = 0
		res = 0
		visited = {start}
		min_heap = []
		for (cost, adj) in graph[start]:
			heapq.heappush(min_heap, (cost, adj))
		while len(visited) < len(points) and min_heap:
			(cost, next_node) = heapq.heappop(min_heap)
			if next_node not in visited:
				visited.add(next_node)
				res += cost
				for (next_cost, adj) in graph[next_node]:
					if adj not in visited:
						heapq.heappush(min_heap, (next_cost, adj))
		return res


class DisjointSet:

	def __init__(self, points):
		self.parent = {}
		self.rank = {}
		for point in points:
			self.parent[point] = point
			self.rank[point] = 1

	def find(self, x):
		if self.parent[x] == x:
			return x
		self.parent[x] = self.find(self.parent[x])
		return self.parent[x]

	def union(self, x, y):
		x_set = self.find(x)
		y_set = self.find(y)
		if self.rank[x_set] < self.rank[y_set]:
			self.parent[x_set] = y_set
		elif self.rank[x_set] > self.rank[y_set]:
			self.parent[y_set] = x_set
		else:
			self.parent[x_set] = y_set
			self.rank[y_set] += 1
from collections import defaultdict

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []
		points = [tuple(point) for point in points]
		disjoint_set = DisjointSet(points)
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				distance = self.distance(points[i], points[j])
				edges.append((distance, points[i], points[j]))
		edges.sort()
		answer = 0
		times = 0
		for (distance, nodeA, nodeB) in edges:
			if disjoint_set.find(nodeA) != disjoint_set.find(nodeB):
				disjoint_set.union(nodeA, nodeB)
				answer += distance
				times += 1
			if times == len(points) - 1:
				return answer
		return answer

	def distance(self, pointA, pointB):
		return abs(pointA[0] - pointB[0]) + abs(pointA[1] - pointB[1])


import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		manhattan = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		(n, c) = (len(points), collections.defaultdict(list))
		for i in range(n):
			for j in range(i + 1, n):
				d = manhattan(points[i], points[j])
				c[i].append((d, j))
				c[j].append((d, i))
		visited = set()
		visited.add(0)
		res = 0
		heap = c[0]
		heapq.heapify(heap)
		while len(visited) < n:
			(d, j) = heapq.heappop(heap)
			if j not in visited:
				visited.add(j)
				res += d
				for record in c[j]:
					heapq.heappush(heap, record)
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		if n == 1:
			return 0
		dis = [(abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j) for i in range(n) for j in range(i + 1, n)]
		heapq.heapify(dis)
		father = list(range(n))

		def getfather(x):
			if father[x] != x:
				father[x] = getfather(father[x])
			return father[x]

		def union(x, y):
			fx = getfather(x)
			fy = getfather(y)
			if fx == fy:
				return False
			father[fx] = fy
			return True
		step = 0
		res = 0
		while dis:
			(d, i, j) = heapq.heappop(dis)
			if union(i, j):
				res += d
				step += 1
				if step == n - 1:
					break
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) < 2:
			return 0

		def dist(p1, p2):
			return abs(points[p1][0] - points[p2][0]) + abs(points[p1][1] - points[p2][1])
		edges = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				edges.append((i, j, dist(i, j)))
		edges = sorted(edges, key=lambda x: x[2])
		total = 0
		group = [x for x in range(len(points))]
		while sum(group) > 0:
			(x, y, w) = edges.pop(0)
			if group[x] == group[y]:
				continue
			gx = group[x]
			gy = group[y]
			g = min(gx, gy)
			for i in range(len(group)):
				if group[i] == gy or group[i] == gx:
					group[i] = g
			total += w
		return total


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		distances = []
		n = len(points)
		for i in range(n - 1):
			for j in range(i + 1, n):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				distances.append([(i, j), dist])
		distances.sort(key=lambda x: x[1])
		parent = [i for i in range(n)]
		size = [1 for _ in range(n)]

		def find(x):
			if parent[x] == x:
				return x
			else:
				return find(parent[x])

		def union(px, py):
			if size[px] < size[py]:
				(px, py) = (py, px)
			parent[py] = px
			size[px] += size[py]
		count = 0
		ans = 0
		for ((x, y), dist) in distances:
			(px, py) = (find(x), find(y))
			if px != py:
				union(px, py)
				count += 1
				ans += dist
				if count == n - 1:
					break
		return ans


class DSU:

	def __init__(self, size):
		self.par = list(range(size))

	def find(self, x):
		if self.par[x] != x:
			return self.find(self.par[x])
		return self.par[x]

	def union(self, x, y):
		self.par[self.find(x)] = self.find(y)

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def distance(u, v):
			return abs(u[0] - v[0]) + abs(u[1] - v[1])
		points_dist = collections.defaultdict(dict)
		edges = []
		for (i, p1) in enumerate(points):
			for j in range(i + 1, len(points)):
				points_dist[i][j] = distance(points[i], points[j])
				heapq.heappush(edges, (distance(points[i], points[j]), i, j))
		res = 0
		count = 0
		dsu = DSU(len(points))
		while count < len(points) - 1:
			(distance, x, y) = heapq.heappop(edges)
			(p_x, p_y) = (dsu.find(x), dsu.find(y))
			if p_x != p_y:
				count += 1
				res += distance
				dsu.union(x, y)
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		dis = []
		for i in range(len(points)):
			for j in range(i, len(points)):
				dis.append((abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j))
		dis = sorted(dis, key=lambda x: x[0])
		joined = 1
		cost = 0
		parents = [x for x in range(len(points))]

		def find(x):
			if parents[x] != x:
				parents[x] = find(parents[x])
			return parents[x]
		for edge in dis:
			if find(edge[1]) != find(edge[2]):
				joined += 1
				cost += edge[0]
				parents[find(edge[1])] = edge[2]
			if joined == len(points):
				return cost


from collections import defaultdict

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []
		n = len(points)
		parent = defaultdict(lambda : -1)

		def find_parent(x, y):
			if parent[x, y] == -1:
				return (x, y)
			else:
				parent[x, y] = find_parent(*parent[x, y])
				return parent[x, y]

		def merge(x1, y1, x2, y2):
			if x1 == x2 and y1 == y2:
				return
			parent_of_i = find_parent(x1, y1)
			parent_of_j = find_parent(x2, y2)
			parent[parent_of_j] = parent_of_i

		def dist(pi, pj):
			return abs(pi[0] - pj[0]) + abs(pi[1] - pj[1])
		for i in range(n - 1):
			for j in range(i + 1, n):
				cost = dist(points[i], points[j])
				edges.append((cost, tuple(points[i]), tuple(points[j])))
		edges.sort(key=lambda e: e[0])
		min_cost = 0
		selected_edge = 0
		for edge in edges:
			(node_v, node_u) = (edge[1], edge[2])
			if find_parent(*node_v) == find_parent(*node_u):
				continue
			merge(*node_v + node_u)
			min_cost += edge[0]
			selected_edge += 1
			if selected_edge == n - 1:
				break
		return min_cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []
		groups = [a for a in range(len(points))]
		for index_a in range(len(points)):
			for index_b in range(index_a + 1, len(points)):
				edge = (index_a, index_b, abs(points[index_a][0] - points[index_b][0]) + abs(points[index_a][1] - points[index_b][1]))
				edges.append(edge)
		edges.sort(key=lambda a: a[2])

		def find(a):
			return a if groups[a] == a else find(groups[a])

		def union(a, b):
			group_a = find(a)
			group_b = find(b)
			if group_a != group_b:
				return (group_a, group_b)
			return
		sum = 0
		while len(set(groups)) != 1:
			edge = edges.pop(0)
			merged = union(edge[0], edge[1])
			if merged is not None:
				groups = [merged[1] if x == merged[0] else x for x in groups]
				sum += edge[2]
		return sum


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		(distances, n) = ({i: [] for i in range(len(points))}, len(points))
		for i in range(n - 1):
			for j in range(i + 1, n):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				distances[i].append((dist, j))
				distances[j].append((dist, i))
		import heapq
		heap = distances[0]
		heapq.heapify(heap)
		ans = 0
		count = 0
		visited = set([0])
		while heap:
			(dist, j) = heapq.heappop(heap)
			if j not in visited:
				visited.add(j)
				ans += dist
				count += 1
				for x in distances[j]:
					heapq.heappush(heap, x)
			if count == n - 1:
				break
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)

		def dist(a, b):
			return abs(a[0] - b[0]) + abs(a[1] - b[1])
		edges = []
		for i in range(n):
			for j in range(i + 1, n):
				edges.append((dist(points[i], points[j]), i, j))
		edges.sort()
		cost = 0
		parent = [i for i in range(n)]
		size = [1] * n

		def find(a):
			if parent[a] == a:
				p = a
			else:
				p = find(parent[a])
			parent[a] = p
			return p

		def union(a, b):
			pa = find(a)
			pb = find(b)
			if pa != pb:
				parent[pa] = pb
				size[pb] += size[pa]
				if size[pb] == n:
					return True
			return False
		for e in edges:
			(a, b) = (e[1], e[2])
			(pa, pb) = (find(a), find(b))
			if pa != pb:
				cost += e[0]
				if union(e[1], e[2]):
					break
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		root = [i for i in range(n + 1)]

		def find(x):
			if root[x] != x:
				root[x] = find(root[x])
			return root[x]

		def uni(x, y):
			(x, y) = (find(x), find(y))
			if x == y:
				return 0
			root[x] = y
			return 1

		def distance(a, b):
			return abs(a[0] - b[0]) + abs(a[1] - b[1])
		routes = []
		unconnected = n - 1
		costs = 0
		for i in range(n):
			for j in range(i + 1, n):
				routes.append([distance(points[i], points[j]), i, j])
		routes.sort(key=lambda l: l[0], reverse=True)
		while unconnected:
			route = routes.pop()
			if uni(route[1], route[2]):
				costs += route[0]
				unconnected -= 1
		return costs


class Solution:

	def minCostConnectPoints(self, p: List[List[int]]) -> int:

		def find(x):
			if dp[x] != x:
				dp[x] = find(dp[x])
			return dp[x]

		def uni(x, y):
			(x, y) = (find(x), find(y))
			if x != y:
				dp[x] = find(y)
				return False
			return True
		n = len(p)
		dp = list(range(n))
		pool = sorted(((abs(p[i][0] - p[j][0]) + abs(p[i][1] - p[j][1]), i, j) for i in range(n) for j in range(i + 1, n)))
		ct = res = 0
		for (dis, u, v) in pool:
			if not uni(u, v):
				res += dis
				ct += 1
				if ct == n - 1:
					break
		return res


from pprint import pprint

class Solution:

	def minCostConnectPoints(self, p: List[List[int]]) -> int:

		def getMinNode(n, val, mst):
			mn = math.inf
			mn_idx = None
			for i in range(n):
				if mst[i] == False and val[i] < mn:
					mn = val[i]
					mn_idx = i
			return mn_idx
		res = 0
		n = len(p)
		parent = [None] * n
		parent[0] = -1
		dists = [[0] * n for _ in range(n)]
		for i in range(n):
			for j in range(n):
				if i != j:
					dists[i][j] = dists[j][i] = abs(p[i][0] - p[j][0]) + abs(p[i][1] - p[j][1])
		mst = [False] * n
		val = [math.inf] * n
		val[0] = 0
		for i in range(n - 1):
			u = getMinNode(n, val, mst)
			mst[u] = True
			for v in range(n):
				if dists[u][v] and mst[v] == False and (dists[u][v] < val[v]):
					val[v] = dists[u][v]
					parent[v] = u
		for i in range(1, n):
			res += dists[parent[i]][i]
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		manhattan = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		(n, c) = (len(points), collections.defaultdict(list))
		for i in range(n):
			for j in range(i + 1, n):
				d = manhattan(points[i], points[j])
				c[i].append((d, j))
				c[j].append((d, i))
		(cnt, ans, visited, heap) = (1, 0, [0] * n, c[0])
		visited[0] = 1
		heapq.heapify(heap)
		while heap:
			(d, j) = heapq.heappop(heap)
			if not visited[j]:
				(visited[j], cnt, ans) = (1, cnt + 1, ans + d)
				for record in c[j]:
					heapq.heappush(heap, record)
			if cnt >= n:
				break
		return ans

	def minCostConnectPoints3(self, points: List[List[int]]) -> int:
		n = len(points)
		if len(points) == 1:
			return 0
		res = 0
		curr = 0
		dis = [math.inf] * n
		explored = set()
		for i in range(n - 1):
			(x0, y0) = points[curr]
			explored.add(curr)
			for (j, (x, y)) in enumerate(points):
				if j in explored:
					continue
				dis[j] = min(dis[j], abs(x - x0) + abs(y - y0))
			(delta, curr) = min(((d, j) for (j, d) in enumerate(dis)))
			dis[curr] = math.inf
			res += delta
		return res

	def minCostConnectPoints2(self, P: List[List[int]]) -> int:
		res = 0
		n = len(P)
		(px, py) = P[0]
		seen = {0}
		todo = set(range(1, n))
		while len(seen) < n:
			mn = float('inf')
			used = -1
			for i in todo:
				(cx, cy) = P[i]
				for j in seen:
					(px, py) = P[j]
					can = abs(cx - px) + abs(cy - py)
					if can < mn:
						mn = can
						used = i
			res += mn
			todo.remove(used)
			seen.add(used)
		return res


from collections import defaultdict

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def find(x):
			if x != parent[x]:
				parent[x] = find(parent[x])
			return parent[x]
		total_points = len(points)
		parent = list(range(total_points))
		weight_matrix = []
		manhattan = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		for i in range(total_points):
			for j in range(i + 1, total_points):
				dist = manhattan(points[i], points[j])
				weight_matrix.append((i, j, dist))
		cost = 0
		for (u, v, w) in sorted(weight_matrix, key=lambda x: x[2]):
			(ru, rv) = (find(u), find(v))
			if ru == rv:
				continue
			cost += w
			parent[ru] = rv
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if not points or len(points) == 1:
			return 0
		dist = {}
		for p in range(1, len(points)):
			dist[p] = abs(points[p][0] - points[0][0]) + abs(points[p][1] - points[0][1])
		print(dist)
		cost = 0
		while dist:
			min_k = 0
			min_v = 10000000000.0
			for (k, v) in list(dist.items()):
				if v < min_v:
					min_v = v
					min_k = k
			print((min_k, min_v))
			cost += min_v
			for (k, v) in list(dist.items()):
				dist[k] = min(dist[k], abs(points[min_k][0] - points[k][0]) + abs(points[min_k][1] - points[k][1]))
			assert dist[min_k] == 0
			del dist[min_k]
		return cost


from collections import defaultdict
import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) < 1:
			return 0
		graph = defaultdict(list)
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				graph[i].append((dist, j))
				graph[j].append((dist, i))
		(heap, visited, cost) = (graph[0], set([0]), 0)
		heapq.heapify(heap)
		while len(visited) != len(points):
			(dist, node) = heapq.heappop(heap)
			if node not in visited:
				visited.add(node)
				for edge in graph[node]:
					heapq.heappush(heap, edge)
				cost += dist
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		if n == 1:
			return 0
		dis = collections.defaultdict(list)
		for i in range(n - 1):
			for j in range(i + 1, n):
				length = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				dis[i].append((length, j))
				dis[j].append((length, i))
		visit = {0}
		queue = collections.deque([0])
		pull = dis[0]
		heapq.heapify(pull)
		cost = 0
		while queue and len(visit) != n:
			node = queue.popleft()
			can = heapq.heappop(pull)
			while can[1] in visit:
				can = heapq.heappop(pull)
			cost += can[0]
			for ele in dis[can[1]]:
				heapq.heappush(pull, ele)
			visit.add(can[1])
			queue.append(can[1])
		return cost


class Solution:

	def find_min_node(self, n, key, mst_set):
		(min, min_node) = (sys.maxsize, -1)
		for i in range(n):
			if not mst_set[i] and key[i] < min:
				(min, min_node) = (key[i], i)
		return min_node

	def solve(self, n, edges):
		mst_set = [False] * n
		key = [sys.maxsize] * n
		parent = [-1] * n
		key[0] = 0
		parent[0] = -1
		for i in range(n):
			u = self.find_min_node(n, key, mst_set)
			mst_set[u] = True
			for v in range(n):
				if not mst_set[v] and edges[u][v] < key[v]:
					parent[v] = u
					key[v] = edges[u][v]
		res = 0
		for i in range(1, n):
			res += edges[parent[i]][i]
		return res

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		edges = [[0] * n for _ in range(n)]
		for i in range(n):
			for j in range(n):
				edges[i][j] = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
		return self.solve(n, edges)


class Solution:

	def minCostConnectPoints(self, p: List[List[int]]) -> int:
		(n, c) = (len(p), collections.defaultdict(list))
		for i in range(n):
			for j in range(i + 1, n):
				d = abs(p[i][0] - p[j][0]) + abs(p[i][1] - p[j][1])
				c[i].append((d, j))
				c[j].append((d, i))
		(cnt, ans, visited, heap) = (1, 0, [0] * n, c[0])
		visited[0] = 1
		heapq.heapify(heap)
		while heap:
			(d, j) = heapq.heappop(heap)
			if not visited[j]:
				(visited[j], cnt, ans) = (1, cnt + 1, ans + d)
				for record in c[j]:
					heapq.heappush(heap, record)
			if cnt >= n:
				break
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []
		cc = [i for i in range(len(points))]
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				d = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				edges.append((d, i, j))
		edges.sort()

		def root(x):
			if cc[x] != x:
				cc[x] = root(cc[x])
			return cc[x]

		def join(x, y):
			rx = root(x)
			ry = root(y)
			if rx != ry:
				cc[rx] = ry
			return rx != ry
		cct = len(points)
		cost = 0
		for (x, i, j) in edges:
			if join(i, j):
				cost += x
				cct -= 1
				if cct == 1:
					break
		return cost


class DSU:

	def __init__(self, N):
		self.parent = [i for i in range(N)]
		self.rank = [0] * N

	def find(self, x):
		if self.parent[x] != x:
			self.parent[x] = self.find(self.parent[x])
		return self.parent[x]

	def union(self, x, y):
		xRoot = self.find(x)
		yRoot = self.find(y)
		if xRoot == yRoot:
			return False
		if self.rank[xRoot] > self.rank[yRoot]:
			self.parent[yRoot] = xRoot
		elif self.rank[yRoot] > self.rank[xRoot]:
			self.parent[xRoot] = yRoot
		else:
			self.parent[yRoot] = xRoot
			self.rank[xRoot] += 1
		return True

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		N = len(points)
		pq = []
		for i in range(N):
			for j in range(i):
				(x1, y1) = points[i]
				(x2, y2) = points[j]
				dist = abs(x1 - x2) + abs(y1 - y2)
				pq.append((dist, i, j))
		heapify(pq)
		dsu = DSU(N)
		edges = 0
		cost = 0
		while edges < N - 1:
			(dist, i, j) = heappop(pq)
			if dsu.union(i, j):
				cost += dist
				edges += 1
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		md = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		n = len(points)
		graph = defaultdict(list)
		for i in range(n):
			for j in range(i + 1, n):
				d = md(points[i], points[j])
				graph[i].append((d, j))
				graph[j].append((d, i))
		visited = {0}
		q = graph[0]
		heapq.heapify(q)
		res = 0
		while len(q) != 0:
			(d, j) = heapq.heappop(q)
			if j not in visited:
				visited.add(j)
				res += d
				for item in graph[j]:
					heapq.heappush(q, item)
			if len(visited) == n:
				break
		return res


from collections import defaultdict
from heapq import heappop, heappush, heapify

def prim(N, E):
	edges = defaultdict(list)
	for (x, y, c) in E:
		edges[x].append((c, y))
		edges[y].append((c, x))
	heap = []
	heappush(heap, (0, 0))
	cnt = 0
	visited = {}
	ans = 0
	while heap:
		(c, n) = heappop(heap)
		if n in visited:
			continue
		visited[n] = 1
		ans += c
		for e in edges[n]:
			heappush(heap, e)
		cnt += 1
		if cnt >= N:
			break
	return ans

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		E = []
		n = len(points)
		for i in range(n):
			for j in range(i + 1, n):
				d = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				E.append((i, j, d))
		ans = prim(n, E)
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		visited = set()
		graph = [[0] * len(points) for _ in range(len(points))]
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				graph[i][j] = graph[j][i] = dist
		heap = [(0, 0)]
		asr = 0
		for i in range(len(points)):
			(dist, idx) = heapq.heappop(heap)
			while heap and idx in visited:
				(dist, idx) = heapq.heappop(heap)
			visited.add(idx)
			asr += dist
			for v in range(len(points)):
				if v not in visited:
					heapq.heappush(heap, (graph[idx][v], v))
		return asr


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		N = len(points)
		dsu = list(range(N))

		def find(i):
			if dsu[i] != i:
				dsu[i] = find(dsu[i])
			return dsu[i]

		def union(i, j):
			dsu[find(j)] = find(i)
		pq = []
		cost = 0
		for i in range(N):
			for j in range(i + 1, N):
				(i_x, i_y) = points[i]
				(j_x, j_y) = points[j]
				c = abs(i_x - j_x) + abs(i_y - j_y)
				pq.append((c, i, j))
		pq.sort(key=lambda x: x[0], reverse=True)
		while pq:
			(c, i, j) = pq.pop()
			if find(i) == find(j):
				continue
			cost += c
			union(i, j)
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				distance = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				edges.append((i, j, distance))
		edges.sort(key=itemgetter(2))
		numComponents = len(points)
		groups = [i for i in range(len(points))]
		size = [1] * len(points)

		def find(x):
			if groups[x] == x:
				return x
			groups[x] = find(groups[x])
			return groups[x]
		cost = 0
		for edge in edges:
			p1 = edge[0]
			p2 = edge[1]
			root1 = find(p1)
			root2 = find(p2)
			if root1 != root2:
				if size[p1] < size[p2]:
					groups[root1] = groups[root2]
					size[root2] += size[root1]
				else:
					groups[root2] = groups[root1]
					size[root1] += size[root2]
				cost += edge[2]
				numComponents -= 1
		if numComponents == 1:
			return cost
		else:
			return -1


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		connections = []
		for (i, p) in enumerate(points):
			for j in range(i + 1, len(points)):
				connections.append((i, j, abs(p[0] - points[j][0]) + abs(p[1] - points[j][1])))
		connections.sort(key=itemgetter(2))
		parent = list(range(len(points)))
		size = [1] * len(points)

		def find(x):
			if x == parent[x]:
				return x
			parent[x] = find(parent[x])
			return parent[x]
		total_distance = 0
		for (u, v, c) in connections:
			p_u = find(u)
			p_v = find(v)
			if p_u == p_v:
				continue
			total_distance += c
			if size[u] < size[v]:
				size[v] += size[u]
				parent[p_u] = p_v
			else:
				size[u] += size[v]
				parent[p_v] = p_u
		return total_distance


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) == 1:
			return 0
		root = {}
		for point in points:
			root[point[0], point[1]] = (point[0], point[1])

		def find(i):
			if i != root[i]:
				root[i] = find(root[i])
			return root[i]

		def union(a, b):
			(a, b) = (find(a), find(b))
			if a == b:
				return 0
			root[a] = b
			return 1
		num = len(points)
		edge_count = 0
		distances = []
		for i in range(num):
			for j in range(i + 1, num):
				distances.append((abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), (points[i], points[j])))
				j += 1
		distances.sort(key=lambda x: x[0])
		ans = 0
		for d in distances:
			a = d[1][0]
			b = d[1][1]
			a_t = tuple(a)
			b_t = tuple(b)
			if find(a_t) != find(b_t):
				edge_count += 1
				ans += d[0]
				union(a_t, b_t)
				if edge_count == num - 1:
					return ans
		return -1


from collections import defaultdict
import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		graph = defaultdict(list)
		manhattan = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				cost = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				graph[i].append((cost, j))
				graph[j].append((cost, i))
		seen = [0] * (len(points) + 1)
		seen[0] = 1
		q = graph[0]
		minimumCost = 0
		connectedNodes = 1
		heapq.heapify(q)
		while q:
			(cost, city) = heapq.heappop(q)
			if not seen[city]:
				seen[city] = 1
				minimumCost += cost
				connectedNodes += 1
				for (connectingCost, neighbour) in graph[city]:
					heapq.heappush(q, (connectingCost, neighbour))
			if connectedNodes >= len(points):
				break
		return minimumCost


from typing import List
import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def find(ds, i):
			if ds[i] < 0:
				return i
			ds[i] = find(ds, ds[i])
			return ds[i]
		(n, ans) = (len(points), 0)
		ds = [-1] * n
		arr = []
		for i in range(n):
			for j in range(i + 1, n):
				heapq.heappush(arr, [abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j])
		while arr:
			(dist, i, j) = heapq.heappop(arr)
			(i, j) = (find(ds, i), find(ds, j))
			if i != j:
				ans += dist
				ds[i] += ds[j]
				ds[j] = i
				if ds[i] == -n:
					break
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		l = len(points)
		if l < 2:
			return 0
		comps = [i for i in range(l)]

		def comp(v):
			return v if comps[v] == v else comp(comps[v])

		def join_comp(comp1, comp2):
			for i in range(l):
				if comps[i] == comp1:
					comps[i] = comp2
		edges = []
		for i in range(l):
			for j in range(i + 1, l):
				edges.append((abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j))
		edges.sort()
		out = 0
		edge_count = l - 1
		for edge in edges:
			comp1 = comp(edge[1])
			comp2 = comp(edge[2])
			if comp1 != comp2:
				out += edge[0]
				join_comp(comp2, comp1)
				edge_count -= 1
				if not edge_count:
					break
		return out


from heapq import *

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		result = 0
		if len(points) == 1:
			return result
		costHeap = []
		n = len(points)
		cur = 0
		distance = lambda p, np: abs(p[0] - np[0]) + abs(p[1] - np[1])
		visited = set()
		visited.add(cur)
		for i in range(1, n):
			heappush(costHeap, [distance(points[0], points[i]), i])
		while costHeap:
			(cost, nextStart) = heappop(costHeap)
			if nextStart not in visited:
				result += cost
				visited.add(nextStart)
				cur = nextStart
				for i in range(n):
					if i in visited:
						continue
					heappush(costHeap, [distance(points[cur], points[i]), i])
			if len(visited) == n:
				break
		return result


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		uf = {}
		n = len(points)
		rank = [1] * n

		def find(x):
			uf.setdefault(x, x)
			if uf[x] != x:
				uf[x] = find(uf[x])
			return uf[x]

		def union(x, y):
			(px, py) = (find(x), find(y))
			if px != py:
				if rank[px] > rank[py]:
					(px, py) = (py, px)
				rank[py] += rank[px]
				uf[px] = py
				return rank[py] == n
			return False
		hp = [(abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j) for i in range(n) for j in range(i + 1, n)]
		heapq.heapify(hp)
		ans = 0
		while hp:
			(d, i, j) = heapq.heappop(hp)
			if find(i) != find(j):
				ans += d
				if union(i, j):
					break
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		from heapq import heappush, heappop
		n = len(points)
		h = {i: {} for i in range(n)}
		visited = [False] * n
		for p1 in range(n):
			for p2 in range(n):
				if p1 == p2:
					continue
				d = abs(points[p1][0] - points[p2][0]) + abs(points[p1][1] - points[p2][1])
				h[p1][p2] = d
				h[p2][p1] = d
		total = 0
		ans = 0
		queue = [(0, 0)]
		while total < n:
			(d, node) = heappop(queue)
			if visited[node]:
				continue
			total += 1
			ans += d
			visited[node] = True
			for item in h[node]:
				if not visited[item]:
					heappush(queue, (h[node][item], item))
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def find(x):
			if x != parent[x]:
				parent[x] = find(parent[x])
			return parent[x]
		parent = list(range(len(points)))
		g = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				g.append((i, j, abs(points[j][1] - points[i][1]) + abs(points[j][0] - points[i][0])))
		cost = 0
		for (u, v, w) in sorted(g, key=lambda x: x[2]):
			(ru, rv) = (find(u), find(v))
			if ru == rv:
				continue
			parent[ru] = rv
			cost += w
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		weight_graph = []
		res = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				weight_graph.append([i, j, abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])])
		weight_graph = sorted(weight_graph, key=lambda item: item[2])
		parent = [i for i in range(n)]
		rank = [0 for _ in range(n)]

		def find(i):
			if parent[i] == i:
				return i
			else:
				return find(parent[i])

		def union(x, y):
			if rank[x] < rank[y]:
				parent[x] = parent[y]
			elif rank[x] > rank[y]:
				parent[y] = parent[x]
			else:
				parent[x] = parent[y]
				rank[y] += 1
		for edge in weight_graph:
			if len(res) < len(points) - 1:
				(u, v, w) = edge
				x = find(u)
				y = find(v)
				if x != y:
					union(x, y)
					res.append(w)
		if not res:
			return 0
		return sum(res)


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		self.points = points
		n = len(points)
		edges = []
		for i in range(n - 1):
			for j in range(i + 1, n):
				d = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				edges.append((d, i, j))
		edges.sort()
		self.comp = list(range(n))
		ans = 0
		e = 0
		for i in range(n - 1):
			while e < len(edges):
				(d, i, j) = edges[e]
				e += 1
				ii = self.find(i)
				jj = self.find(j)
				if ii != jj:
					self.comp[ii] = jj
					ans += d
					break
		return ans

	def find(self, i):
		idx = []
		while self.comp[i] != i:
			idx.append(i)
			i = self.comp[i]
		for j in idx:
			self.comp[j] = i
		return i


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		cost = 0
		if n <= 1:
			return 0
		g = []
		for i in range(n):
			x1 = points[i][0]
			y1 = points[i][1]
			for j in range(i + 1, n):
				if j != i:
					x2 = points[j][0]
					y2 = points[j][1]
					d = abs(x1 - x2) + abs(y1 - y2)
					g.append([i, j, d])
		g.sort(key=lambda x: x[2])
		par = [-1] * n
		for (i, (u, v, c)) in enumerate(g):
			p1 = u
			while par[p1] > 0:
				p1 = par[p1]
			p2 = v
			while par[p2] > 0:
				p2 = par[p2]
			if p1 == p2:
				continue
			else:
				if abs(par[p1]) > abs(par[p2]):
					par[p1] += par[p2]
					if u != p1:
						par[u] = p1
					par[v] = p1
					par[p2] = p1
				else:
					par[p2] += par[p1]
					if v != p2:
						par[v] = p2
					par[u] = p2
					par[p1] = p2
				cost += c
		return cost


from collections import defaultdict

class Graph:

	def __init__(self, n: int) -> None:
		self.V = n
		self.graph = []

	def addEdge(self, u: int, v: int, w: int) -> None:
		self.graph.append([u, v, w])

	def find(self, parent: List[int], i: int) -> int:
		if parent[i] == i:
			return i
		return self.find(parent, parent[i])

	def union(self, parent: List[int], rank: List[int], x: int, y: int) -> None:
		xroot = self.find(parent, x)
		yroot = self.find(parent, y)
		if rank[xroot] < rank[yroot]:
			parent[xroot] = yroot
		elif rank[xroot] > rank[yroot]:
			parent[yroot] = xroot
		else:
			parent[yroot] = xroot
			rank[xroot] += 1

	def KruskalMST(self) -> List[List[int]]:
		result = []
		i = 0
		e = 0
		self.graph = sorted(self.graph, key=lambda item: item[2])
		parent = []
		rank = []
		for node in range(self.V):
			parent.append(node)
			rank.append(0)
		while e < self.V - 1:
			(u, v, w) = self.graph[i]
			i = i + 1
			x = self.find(parent, u)
			y = self.find(parent, v)
			if x != y:
				e = e + 1
				result.append([u, v, w])
				self.union(parent, rank, x, y)
		return result

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		graph = Graph(n)
		for i in range(n - 1):
			point1 = points[i]
			for j in range(i + 1, n):
				point2 = points[j]
				manhattan_distance = abs(point1[0] - point2[0]) + abs(point1[1] - point2[1])
				graph.addEdge(i, j, manhattan_distance)
		ans = 0
		for edge in graph.KruskalMST():
			ans += edge[2]
		return ans


class Graph:

	def __init__(self, vertices):
		self.V = vertices
		self.graph = []

	def addEdge(self, u, v, w):
		self.graph.append([u, v, w])

	def find(self, parent, i):
		if parent[i] == i:
			return i
		return self.find(parent, parent[i])

	def union(self, parent, rank, x, y):
		px = self.find(parent, x)
		py = self.find(parent, y)
		if rank[px] < rank[py]:
			parent[px] = py
		elif rank[px] > rank[py]:
			parent[py] = px
		else:
			parent[py] = px
			rank[px] += 1

	def MST(self):
		res = 0
		i = 0
		e = 0
		self.graph = sorted(self.graph, key=lambda item: item[2])
		parent = []
		rank = []
		for node in range(self.V):
			parent.append(node)
			rank.append(0)
		while e < self.V - 1:
			(u, v, w) = self.graph[i]
			i = i + 1
			x = self.find(parent, u)
			y = self.find(parent, v)
			if x != y:
				e = e + 1
				res += w
				self.union(parent, rank, x, y)
		return res

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		g = Graph(n)

		def dis(i, j):
			return abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
		for i in range(n):
			for j in range(i + 1, n):
				g.addEdge(i, j, dis(i, j))
		return g.MST()


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def distance(p1, p2):
			return abs(p2[0] - p1[0]) + abs(p2[1] - p1[1])
		(res, n) = (0, len(points))
		dist_list = [distance(points[0], p) for p in points]
		for _ in range(n - 1):
			(d, j) = min(((d, i) for (i, d) in enumerate(dist_list) if d > 0))
			res += d
			dist_list = [min(dist_list[i], distance(points[j], p)) for (i, p) in enumerate(points)]
		return res


class UnionFind:

	def __init__(self, size):
		self._parent = list(range(size))
		self._size = [1] * size

	def union(self, a, b):
		(a, b) = (self.find(a), self.find(b))
		if a == b:
			return False
		if self._size[a] < self._size[b]:
			(a, b) = (b, a)
		self._parent[b] = a
		self._size[a] += self._size[b]
		return True

	def find(self, x):
		while self._parent[x] != x:
			self._parent[x] = self._parent[self._parent[x]]
			x = self._parent[x]
		return x

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		edges = []
		for u in range(n):
			(x0, y0) = points[u]
			for v in range(u + 1, n):
				(x1, y1) = points[v]
				edges.append((u, v, abs(x0 - x1) + abs(y0 - y1)))
		edges.sort(key=lambda e: e[2])
		uf = UnionFind(n)
		cost = 0
		for (u, v, w) in edges:
			if uf.union(u, v):
				cost += w
		return cost


class Solution:

	def minCostConnectPoints(self, A: List[List[int]]) -> int:
		self.graph = []

		def find(par, i):
			if par[i] == i:
				return i
			return find(par, par[i])

		def union(par, rank, x, y):
			xroot = find(par, x)
			yroot = find(par, y)
			if rank[xroot] < rank[yroot]:
				par[xroot] = yroot
			elif rank[xroot] > rank[yroot]:
				par[yroot] = xroot
			else:
				par[yroot] = xroot
				rank[xroot] += 1

		def kruskal():
			result = []
			i = 0
			e = 0
			self.graph = sorted(edges, key=lambda item: item[2])
			par = []
			rank = []
			for node in range(len(A)):
				par.append(node)
				rank.append(0)
			while e < len(A) - 1:
				(u, v, w) = self.graph[i]
				i = i + 1
				x = find(par, u)
				y = find(par, v)
				if x != y:
					e = e + 1
					result.append([u, v, w])
					union(par, rank, x, y)
			return result
		edge = defaultdict(list)
		edges = []
		for i in range(len(A)):
			for j in range(i + 1, len(A)):
				x = abs(A[i][0] - A[j][0])
				y = abs(A[i][1] - A[j][1])
				edges.append([i, j, x + y])
		res = kruskal()
		main = 0
		for i in res:
			main += i[-1]
		return main


def find_root(parents, i):
	if parents[i] == -1:
		return i
	else:
		return find_root(parents, parents[i])

def calc_dist(p1, p2):
	return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) == 1:
			return 0
		graph = []
		n = len(points)
		for i in range(len(points) - 1):
			for j in range(i + 1, len(points)):
				dist = calc_dist(points[i], points[j])
				heapq.heappush(graph, [dist, (i, j)])
		parents = [-1] * len(points)
		cost = 0
		count = 0
		while count < n - 1:
			(dist, point_pair) = heapq.heappop(graph)
			(p1, p2) = (point_pair[0], point_pair[1])
			r1 = find_root(parents, p1)
			r2 = find_root(parents, p2)
			if r1 != r2:
				parents[r1] = r2
				cost = cost + dist
				count = count + 1
		return cost


class Solution:

	def minCostConnectPoints(self, points):
		n = len(points)
		graph = [[] for i in range(n)]
		for i in range(n):
			for j in range(i + 1, n):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				graph[i].append([j, dist])
				graph[j].append([i, dist])
		return mst(n, graph)

def mst(n, graph):
	keyval = [2 ** 31 - 1] * n
	keyval[0] = 0
	mst = [False] * n
	for i in range(n):
		u = minVal(keyval, mst)
		mst[u] = True
		for node in graph[u]:
			if mst[node[0]] == False and keyval[node[0]] > node[1]:
				keyval[node[0]] = node[1]
	return sum(keyval[1:])

def minVal(keyval, mst):
	minv = 2 ** 31 - 1
	minInd = 0
	for i in range(1, len(keyval)):
		if minv > keyval[i] and mst[i] == False:
			minv = keyval[i]
			minInd = i
	return minInd


from typing import List

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		N = len(points)
		P = [i for i in range(N)]
		E = []
		for u in range(N):
			(x1, y1) = points[u]
			for v in range(u + 1, N):
				(x2, y2) = points[v]
				E.append((u, v, abs(x1 - x2) + abs(y1 - y2)))
		E.sort(key=lambda edge: edge[2])

		def getParent(x):
			if x != P[x]:
				P[x] = getParent(P[x])
			return P[x]

		def join(u, v):
			pu = getParent(u)
			pv = getParent(v)
			if pu == pv:
				return False
			P[pu] = pv
			return True
		(rs, count) = (0, 0)
		for (u, v, w) in E:
			if join(u, v):
				rs = rs + w
				count = count + 1
			if count == N:
				break
		return rs


class UnionFindSet:

	def __init__(self, n):
		self.parents = [i for i in range(n + 1)]
		self.ranks = [0 for i in range(n + 1)]

	def find(self, u):
		if u != self.parents[u]:
			self.parents[u] = self.find(self.parents[u])
		return self.parents[u]

	def union(self, u, v):
		pu = self.find(u)
		pv = self.find(v)
		if pu == pv:
			return False
		if self.ranks[pu] < self.ranks[pv]:
			self.parents[pu] = pv
		elif self.ranks[pu] > self.ranks[pv]:
			self.parents[pv] = pu
		else:
			self.parents[pu] = pv
			self.ranks[pv] += 1
		return True

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		edges = []
		for i in range(n):
			for j in range(i + 1, n):
				edges.append([abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j])
		edges.sort()
		ans = 0
		count = 0
		uf = UnionFindSet(n)
		for e in edges:
			if not uf.union(e[1], e[2]):
				continue
			ans += e[0]
			count += 1
			if count == n - 1:
				return ans
		return ans


from heapq import *

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) <= 1:
			return 0
		edge_list = []
		for (idx1, [x1, y1]) in enumerate(points):
			for (idx2, [x2, y2]) in enumerate(points[idx1 + 1:], idx1 + 1):
				heappush(edge_list, [abs(x1 - x2) + abs(y1 - y2), idx1, idx2])
		(cost, p1, p2) = heappop(edge_list)
		add_point = {p1, p2}
		ret = cost
		while len(add_point) != len(points) and edge_list:
			temp_list = []
			flag = False
			while not flag:
				(cost, p1, p2) = heappop(edge_list)
				if p1 in add_point and p2 in add_point:
					continue
				elif p1 not in add_point and p2 not in add_point:
					temp_list.append([cost, p1, p2])
				else:
					add_point.add(p1)
					add_point.add(p2)
					ret += cost
					flag = True
			while temp_list:
				heappush(edge_list, heappop(temp_list))
		return ret


def cost(x, y):
	return abs(x[0] - y[0]) + abs(x[1] - y[1])

def find(z):
	nonlocal p
	a = []
	while p[z] != z:
		a.append(z)
		z = p[z]
	for i in a:
		p[i] = z
	return z

class Solution:

	def minCostConnectPoints(self, a: List[List[int]]) -> int:
		nonlocal p
		n = len(a)
		b = []
		p = [i for i in range(n + 1)]
		s = [1 for i in range(n + 1)]
		for i in range(n):
			for j in range(i + 1, n):
				b.append((i, j, cost(a[i], a[j])))
		b.sort(key=lambda x: x[2])
		su = 0
		for i in b:
			x = find(i[0])
			y = find(i[1])
			if x != y:
				su += i[2]
				if s[x] > s[y]:
					p[y] = x
					s[x] += s[y]
				else:
					p[x] = y
					s[y] += s[x]
		return su


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def find(x):
			if uf[x] != x:
				uf[x] = find(uf[x])
			return uf[x]

		def union(x, y):
			idx = find(x)
			idy = find(y)
			if idx == idy:
				return
			uf[idy] = idx

		def dist(x, y):
			return abs(y[0] - x[0]) + abs(y[1] - x[1])
		n = len(points)
		uf = {i: i for i in range(n)}
		edges = []
		for i in range(n):
			for j in range(i + 1, n):
				a = points[i]
				b = points[j]
				edges.append((i, j, dist(a, b)))
		edges = sorted(edges, key=lambda x: x[2])
		cost = 0
		for edge in edges:
			x = edge[0]
			y = edge[1]
			if find(x) != find(y):
				union(x, y)
				cost += edge[2]
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		ok = [-1 for i in range(len(points))]

		def union(x, y):
			x1 = find(x)
			x2 = find(y)
			ok[x1] = x2

		def find(x):
			if ok[x] == -1:
				return x
			else:
				ok[x] = find(ok[x])
				return ok[x]
		d = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				d.append([abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j])
		d.sort()
		ans = 0
		count = 0
		for i in d:
			x = find(i[1])
			y = find(i[2])
			if x != y:
				union(i[1], i[2])
				ans += i[0]
				count += 1
			if count == len(points) - 1:
				return ans
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		manhattan = lambda u, v: abs(u[0] - v[0]) + abs(u[1] - v[1])
		from collections import defaultdict
		n = len(points)
		graph = defaultdict(list)
		for i in range(n - 1):
			for j in range(i + 1, n):
				w = manhattan(points[i], points[j])
				graph[i].append((w, j))
				graph[j].append((w, i))
		k = 0
		costs = 0
		seen = [False] * n
		heap = [(0, 0)]
		while heap:
			(w, u) = heapq.heappop(heap)
			if not seen[u]:
				seen[u] = True
				costs += w
				k += 1
				if k == n:
					break
				for (ew, v) in graph[u]:
					heapq.heappush(heap, (ew, v))
		return costs


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		manhattan = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		(n, graph) = (len(points), collections.defaultdict(dict))
		for i in range(n):
			for j in range(i + 1, n):
				d = manhattan(points[i], points[j])
				graph[i][j] = graph[j][i] = d
		(cnt, ans, visited) = (0, 0, [0] * n)
		heap = [(0, 0)]
		d = [float('inf')] * n
		d[0] = 0
		while heap:
			(cost, node) = heapq.heappop(heap)
			if visited[node]:
				continue
			(visited[node], cnt, ans) = (1, cnt + 1, ans + cost)
			for nex in graph[node]:
				if d[nex] > graph[node][nex]:
					d[nex] = graph[node][nex]
					heapq.heappush(heap, (d[nex], nex))
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		cache = list(range(len(points)))

		def find(val):
			if cache[val] != val:
				cache[val] = find(cache[val])
			return cache[val]

		def union(x, y):
			cache[find(x)] = cache[find(y)]
		dists = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				dists.append((dist, i, j))
		dists.sort()
		ans = 0
		count = 0
		n = len(points)
		for (dist, a, b) in dists:
			if find(a) != find(b):
				count += 1
				ans += dist
				union(a, b)
			if count >= n - 1:
				break
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		import heapq
		graph = self.build_graph(points)
		min_heap = []
		start = 0
		for (dist, node) in graph[start]:
			heapq.heappush(min_heap, (dist, node))
		visited = set()
		visited.add(start)
		res = cnt = 0
		while len(min_heap) > 0:
			(dist, node) = heapq.heappop(min_heap)
			if cnt == len(points) - 1:
				break
			if node not in visited:
				res += dist
				cnt += 1
				visited.add(node)
				for (nxt_dist, nxt_node) in graph[node]:
					heapq.heappush(min_heap, (nxt_dist, nxt_node))
		return res

	def build_graph(self, points):
		from collections import defaultdict
		graph = defaultdict(list)
		for i in range(len(points)):
			for j in range(len(points)):
				if i == j:
					continue
				graph[i].append((self.dist(points[i], points[j]), j))
		return graph

	def dist(self, p0, p1):
		(x0, y0) = p0
		(x1, y1) = p1
		return abs(x1 - x0) + abs(y1 - y0)


class Solution:

	def minCostConnectPoints(self, A: List[List[int]]) -> int:
		n = len(A)
		distance_arr = []
		for i in range(n):
			for j in range(i + 1, n):
				distance_arr.append([abs(A[j][0] - A[i][0]) + abs(A[j][1] - A[i][1]), i, j])
		distance_arr.sort()
		root = [i for i in range(n)]

		def find(x):
			if root[x] != x:
				root[x] = find(root[x])
			return root[x]
		cnt = 0
		sm = 0
		for (dis, x, y) in distance_arr:
			if find(x) == find(y):
				continue
			root[find(x)] = find(y)
			cnt += 1
			sm += dis
			if cnt == n - 1:
				break
		return sm


class Solution:

	def find(self, roots, x):
		if x == roots[x]:
			return x
		return self.find(roots, roots[x])

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []
		n = len(points)
		for i in range(n):
			for j in range(i + 1, n):
				(x1, y1) = points[i]
				(x2, y2) = points[j]
				d = abs(x1 - x2) + abs(y1 - y2)
				edges.append((d, i, j))
		edges.sort()
		roots = list(range(n))
		ranks = [0] * n
		count = 0
		res = 0
		for (d, x, y) in edges:
			rx = self.find(roots, x)
			ry = self.find(roots, y)
			if rx != ry:
				if ranks[rx] > ranks[ry]:
					roots[ry] = rx
				elif ranks[rx] < ranks[ry]:
					roots[rx] = ry
				else:
					roots[ry] = rx
					ranks[rx] += 1
				count += 1
				res += d
				if count == n - 1:
					return res
		return res


class UnionFind:

	def __init__(self):
		self.parents = {}
		self.sizes = {}

	def findParent(self, x):
		if x not in self.parents:
			self.parents[x] = x
			self.sizes[x] = 1
			return x
		if self.parents[x] != x:
			self.parents[x] = self.findParent(self.parents[x])
		return self.parents[x]

	def union(self, x, y):
		(rootX, rootY) = (self.findParent(x), self.findParent(y))
		if rootX == rootY:
			return
		if self.sizes[rootX] < self.sizes[rootY]:
			self.sizes[rootY] += self.sizes[rootX]
			self.parents[rootX] = rootY
		else:
			self.sizes[rootX] += self.sizes[rootY]
			self.parents[rootY] = rootX

	def numberOfComponents(self):
		return sum((1 for (x, p) in self.parents.items() if x == p))

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def dist(x1, y1, x2, y2):
			return abs(x1 - x2) + abs(y1 - y2)
		uf = UnionFind()
		N = len(points)
		edges = []
		ans = 0
		for i in range(N):
			for j in range(i + 1, N):
				([x1, y1], [x2, y2]) = (points[i], points[j])
				edges.append([dist(x1, y1, x2, y2), i, j])
		edges.sort()
		ans = 0
		edgesTaken = 0
		i = 0
		while edgesTaken < N - 1:
			(d, x, y) = edges[i]
			if uf.findParent(x) != uf.findParent(y):
				uf.union(x, y)
				ans += d
				edgesTaken += 1
			i += 1
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def minnode(n, keyval, mstset):
			mini = 999999999999
			mini_index = None
			for i in range(n):
				if mstset[i] == False and keyval[i] < mini:
					mini = keyval[i]
					mini_index = i
			return mini_index

		def findcost(n, city):
			parent = [None] * n
			keyval = [None] * n
			mstset = [None] * n
			for i in range(n):
				keyval[i] = 9999999999999
				mstset[i] = False
			parent[0] = -1
			keyval[0] = 0
			for i in range(n - 1):
				u = minnode(n, keyval, mstset)
				mstset[u] = True
				for v in range(n):
					if city[u][v] and mstset[v] == False and (city[u][v] < keyval[v]):
						keyval[v] = city[u][v]
						parent[v] = u
			cost = 0
			for i in range(1, n):
				cost += city[parent[i]][i]
			return cost
		n = len(points)
		city = [[0 for c in range(n)] for r in range(n)]
		for r in range(n):
			c1 = points[r]
			for c in range(n):
				c2 = points[c]
				val = abs(points[r][0] - points[c][0]) + abs(points[r][1] - points[c][1])
				city[r][c] = val
		return findcost(n, city)


from queue import PriorityQueue
import math

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		q = []
		for i in range(len(points)):
			(xi, yi) = points[i]
			for j in range(i + 1, len(points)):
				(xj, yj) = points[j]
				q.append([abs(xi - xj) + abs(yi - yj), i, j])
		q = sorted(q)
		cost = 0
		self.arr = [-1 for el in range(len(points))]
		for el in q:
			(d, p1, p2) = (el[0], el[1], el[2])
			cycle = self.isCycle(p1, p2)
			if not cycle:
				cost += d
				self.combinePoints(p1, p2)
			else:
				continue
			if self.isDone():
				break
		return cost

	def isDone(self):
		n_neg = 0
		for val in self.arr:
			if val < 0:
				n_neg += 1
		if n_neg == 1:
			return True
		return False

	def combinePoints(self, p1, p2):
		(parent1, children1) = self.getParent(p1, [])
		size1 = self.arr[parent1]
		(parent2, children2) = self.getParent(p2, [])
		size2 = self.arr[parent2]
		if abs(size2) > abs(size1):
			self.arr[parent1] = parent2
			self.arr[parent2] = size2 + size1
			self.updateChildren(children1, parent2)
		else:
			self.arr[parent2] = parent1
			self.arr[parent1] = size2 + size1
			self.updateChildren(children2, parent1)

	def isCycle(self, p1, p2):
		(parent1, _) = self.getParent(p1, [])
		(parent2, _) = self.getParent(p2, [])
		if parent1 == parent2:
			return True
		else:
			return False

	def getParent(self, p1, children):
		if self.arr[p1] < 0:
			return (p1, children)
		else:
			children.append(p1)
			return self.getParent(self.arr[p1], children)

	def updateChildren(self, children, parent):
		for child in children:
			self.arr[child] = parent


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		dist = []
		n = len(points)
		for i in range(n):
			for j in range(i):
				p1 = points[i]
				p2 = points[j]
				dist.append((abs(p1[0] - p2[0]) + abs(p1[1] - p2[1]), i, j))
		dist.sort()
		ps = list(range(n))

		def find(x):
			while ps[x] != x:
				ps[x] = ps[ps[x]]
				x = ps[x]
			return x

		def union(x, y):
			px = find(x)
			py = find(y)
			if px == py:
				return False
			else:
				ps[px] = py
				return True
		res = 0
		for (d, x, y) in dist:
			if union(x, y):
				res += d
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		vertices = {}
		(x, y) = (points[0][0], points[0][1])
		for (u, v) in points:
			vertices[u, v] = abs(u - x) + abs(v - y)

		def mindistance() -> tuple:
			Node = None
			for node in vertices:
				if not Node:
					Node = node
				elif vertices[node] < vertices[Node]:
					Node = node
			return Node
		n = len(points)
		Cost = 0
		for i in range(n):
			temp = mindistance()
			Cost += vertices[temp]
			vertices.pop(temp)
			for c in vertices:
				vertices[c] = min(vertices[c], abs(c[0] - temp[0]) + abs(c[1] - temp[1]))
		return Cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		parents = {}

		def find(p):
			if p not in parents:
				parents[p] = p
			if parents[p] != p:
				parents[p] = find(parents[p])
			return parents[p]

		def merge(p, q):
			(i, j) = (find(p), find(q))
			if i != j:
				parents[j] = i

		def isconnected(p, q):
			return find(p) == find(q)
		n = len(points)
		pq = []
		for i in range(n):
			for j in range(i + 1, n):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				heapq.heappush(pq, [dist, i, j])
		edge = 0
		res = 0
		while edge < n - 1:
			(dist, i, j) = heapq.heappop(pq)
			if isconnected(i, j):
				continue
			else:
				edge += 1
				res += dist
				merge(i, j)
		return res


class Ufs:

	def __init__(self, n):
		self.p = [i for i in range(n)]
		self.rank = [0 for i in range(n)]

	def find(self, i):
		if self.p[i] != i:
			self.p[i] = self.find(self.p[i])
		return self.p[i]

	def union(self, a, b):
		aroot = self.find(a)
		broot = self.find(b)
		if aroot == broot:
			return
		if self.rank[aroot] < self.rank[broot]:
			self.p[aroot] = broot
		elif self.rank[aroot] > self.rank[broot]:
			self.p[broot] = aroot
		else:
			self.p[aroot] = broot
			self.rank[broot] += 1

	def connect(self, a, b):
		if self.find(a) == self.find(b):
			return True
		else:
			return False

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		calc = lambda x, y: abs(x[0] - y[0]) + abs(x[1] - y[1])
		edges = []
		n = len(points)
		vis = {}
		for i in range(n):
			for j in range(i + 1, n):
				edges.append([calc(points[i], points[j]), i, j])
		edges.sort()
		ans = 0
		ufs = Ufs(n)
		cnt = i = 0
		while cnt < n - 1:
			(w, u, v) = edges[i]
			i += 1
			if ufs.connect(u, v):
				continue
			ans += w
			ufs.union(u, v)
			cnt += 1
		return ans


from collections import defaultdict

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = defaultdict(list)
		n = len(points)
		for i in range(n - 1):
			(x, y) = points[i]
			for j in range(i + 1, n):
				(u, v) = points[j]
				d = abs(x - u) + abs(y - v)
				edges[d].append((i, j))
		find = {i: i for i in range(n)}
		union = {i: set([i]) for i in range(n)}
		cost = 0
		m = n - 1
		min_edges = sorted(edges.keys())
		while m > 0:
			d = min_edges.pop(0)
			j = 0
			while m > 0 and j < len(edges[d]):
				(u, v) = edges[d][j]
				if find[u] != find[v]:
					x = min(find[u], find[v])
					y = max(find[u], find[v])
					for z in union[y]:
						find[z] = x
					union[x] = union[x] | union[y]
					cost += d
					m -= 1
				j += 1
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def find(u):
			while parents[u] >= 0:
				u = parents[u]
			return u

		def union(u, v):
			if parents[u] < parents[v]:
				parents[u] += parents[v]
				parents[v] = u
			else:
				parents[v] += parents[u]
				parents[u] = v
		n = len(points)
		costs = {}
		for i in range(n):
			for j in range(i + 1, n):
				costs[i, j] = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
		sorted_costs = sorted(list(costs.items()), key=lambda cost: -cost[1])
		s = set()
		cost = 0
		parents = [-1] * n
		while sorted_costs:
			((u, v), weight) = sorted_costs.pop()
			pu = find(u)
			pv = find(v)
			if pu != pv:
				union(pu, pv)
				cost += weight
		return cost


from queue import PriorityQueue as PQ

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		dist = [[] for _ in range(n)]
		for i in range(n):
			(xi, yi) = points[i]
			for j in range(i + 1, n):
				(xj, yj) = points[j]
				d = abs(xi - xj) + abs(yi - yj)
				dist[i].append((j, d))
				dist[j].append((i, d))
		chosen = set([0])
		pq = PQ()
		seen = [0] * n
		for (i, d) in dist[0]:
			pq.put((d, i))
			seen[i] = d
		(ans, edges) = (0, 0)
		while not pq.empty() and edges < n - 1:
			(d, i) = pq.get()
			if i not in chosen:
				chosen.add(i)
				ans += d
				edges += 1
				for (j, dj) in dist[i]:
					if j not in chosen and dj < seen[j]:
						pq.put((dj, j))
						seen[j] = dj
		return ans


class DisjointSet:

	def __init__(self, n):
		self.parent = [i for i in range(n)]
		self.rank = [1 for i in range(n)]

	def find(self, a):
		if self.parent[a] == a:
			return a
		self.parent[a] = self.find(self.parent[a])
		return self.parent[a]

	def union(self, a, b):
		(pa, pb) = (self.parent[a], self.parent[b])
		if pa == pb:
			return
		if self.rank[a] > self.rank[b]:
			self.parent[pb] = pa
			self.rank[pa] += self.rank[pb]
		else:
			self.parent[pa] = pb
			self.rank[pb] += self.rank[pa]

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		man_dist = lambda a, b: abs(a[0] - b[0]) + abs(a[1] - b[1])
		n = len(points)
		all_dists = []
		for i in range(n):
			for j in range(i + 1, n):
				all_dists.append((man_dist(points[i], points[j]), i, j))
		all_dists.sort(key=lambda x: x[0])
		ans = 0
		dis_set = DisjointSet(n)
		for (dist, u, v) in all_dists:
			if dis_set.find(u) != dis_set.find(v):
				dis_set.union(u, v)
				ans += dist
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) == 1:
			return 0
		neibors = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				point1 = points[i]
				point2 = points[j]
				dis = abs(point1[0] - point2[0]) + abs(point1[1] - point2[1])
				neibors.append((dis, i, j))
		neibors_sorted = sorted(neibors)
		unions = {i: i for i in range(len(points))}

		def find(i):
			if unions[i] == i:
				return i
			else:
				unions[i] = find(unions[i])
				return unions[i]
		ret = 0
		line = 0
		for neibor in neibors_sorted:
			if find(neibor[1]) != find(neibor[2]):
				unions[find(neibor[1])] = find(neibor[2])
				ret += neibor[0]
				line += 1
				if line == len(points) - 1:
					return ret
			else:
				continue


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) == 0:
			return 0
		heap = []
		for i in range(1, len(points)):
			heapq.heappush(heap, (abs(points[i][0] - points[0][0]) + abs(points[i][1] - points[0][1]), i))
		ret = 0
		while heap:
			(cost, e_pop) = heapq.heappop(heap)
			ret += cost
			heap_new = []
			for (cost_old, e) in heap:
				heapq.heappush(heap_new, (min(cost_old, abs(points[e][0] - points[e_pop][0]) + abs(points[e][1] - points[e_pop][1])), e))
			heap = heap_new
		return ret


class Solution:

	def getWeight(self, x, y):
		(xi, xj) = (x[0], x[1])
		(yi, yj) = (y[0], y[1])
		return abs(xi - yi) + abs(xj - yj)

	def find(self, parent, i):
		if parent[i] == i:
			return i
		return self.find(parent, parent[i])

	def union(self, parent, rank, x, y):
		xroot = self.find(parent, x)
		yroot = self.find(parent, y)
		if rank[xroot] < rank[yroot]:
			parent[xroot] = yroot
		elif rank[xroot] > rank[yroot]:
			parent[yroot] = xroot
		else:
			parent[yroot] = xroot
			rank[xroot] += 1

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		E = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				u = points[i]
				v = points[j]
				E.append([i, j, self.getWeight(u, v)])
		E = sorted(E, key=lambda item: item[2])
		parent = []
		rank = []
		for node in range(len(points)):
			parent.append(node)
			rank.append(0)
		e = 0
		i = 0
		result = 0
		while e < len(points) - 1:
			(u, v, w) = E[i]
			i += 1
			x = self.find(parent, u)
			y = self.find(parent, v)
			if x != y:
				e += 1
				result += w
				self.union(parent, rank, x, y)
		return result


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		N = len(points)

		def distance(p1, p2):
			return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		ans = 0
		h = []
		heappush(h, (0, points[0]))
		visited = set()
		while h:
			(d, p) = heappop(h)
			if (p[0], p[1]) in visited:
				continue
			visited.add((p[0], p[1]))
			ans += d
			for point in points:
				if (point[0], point[1]) not in visited:
					heappush(h, (distance(p, point), point))
			if len(visited) == N:
				break
		return ans

	def minCostConnectPoints_2(self, points: List[List[int]]) -> int:
		manhattan = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		(n, c) = (len(points), collections.defaultdict(list))
		for i in range(n):
			for j in range(i + 1, n):
				d = manhattan(points[i], points[j])
				c[i].append((d, j))
				c[j].append((d, i))
		(cnt, ans, visited, heap) = (1, 0, [0] * n, c[0])
		visited[0] = 1
		heapq.heapify(heap)
		while heap:
			(d, j) = heapq.heappop(heap)
			if not visited[j]:
				(visited[j], cnt, ans) = (1, cnt + 1, ans + d)
				for record in c[j]:
					heapq.heappush(heap, record)
			if cnt >= n:
				break
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		npoints = len(points)
		if npoints == 1:
			return 0
		edges = dict()
		for i in range(npoints):
			for j in range(i + 1, npoints):
				edges[i, j] = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
		sortededges = {k: v for (k, v) in sorted(edges.items(), key=lambda item: item[1])}
		parent = [i for i in range(npoints)]
		mincost = 0
		numedges = 0
		for edge in sortededges:
			if self.findParent(parent, edge[0]) == self.findParent(parent, edge[1]):
				continue
			else:
				mincost += sortededges[edge]
				self.union(parent, edge[0], edge[1])
				numedges += 1
				if numedges == npoints - 1:
					return mincost

	def findParent(self, parent, i):
		if parent[i] == i:
			return i
		return self.findParent(parent, parent[i])

	def union(self, parent, u, v):
		u_set = self.findParent(parent, u)
		v_set = self.findParent(parent, v)
		parent[u_set] = v_set


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def manhantan_distance(x, y):
			return abs(x[0] - y[0]) + abs(x[1] - y[1])
		n = len(points)
		included = {0}
		distances = [manhantan_distance(points[0], point) for point in points]
		cost = 0
		while len(included) < n:
			to_add = None
			cost_to_add = float('inf')
			for (i, distance) in enumerate(distances):
				if i in included:
					continue
				if distance < cost_to_add:
					to_add = i
					cost_to_add = distance
			included.add(to_add)
			cost += cost_to_add
			new_point = points[to_add]
			for (i, point) in enumerate(points):
				new_distance = manhantan_distance(new_point, point)
				distances[i] = min(distances[i], new_distance)
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		if n == 1:
			return 0
		d = []
		for (i, (xi, yi)) in enumerate(points[:-1]):
			for (j, (xj, yj)) in enumerate(points[i + 1:]):
				d.append([i, i + j + 1, abs(xj - xi) + abs(yj - yi)])
		d = sorted(d, key=lambda r: r[2])
		father = {i: i for i in range(n)}

		def find(x):
			if x != father[x]:
				father[x] = find(father[x])
			return father[x]
		(res, c) = (0, 0)
		for (i, j, distance) in d:
			if find(i) != find(j):
				father[find(i)] = j
				res += distance
				c += 1
				if c == n - 1:
					return res


class Solution:

	def minCostConnectPoints(self, p: List[List[int]]) -> int:
		n = len(p)
		parents = list(range(n))

		def find(x):
			if parents[x] != x:
				parents[x] = find(parents[x])
			return parents[x]

		def union(x, y):
			r1 = find(x)
			r2 = find(y)
			if r1 != r2:
				parents[r2] = r1
				return True
			else:
				return False

		def dist(p1, p2):
			return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		a = []
		for i in range(n):
			for j in range(i + 1, n):
				d = dist(p[i], p[j])
				a.append((d, i, j))
		a.sort()
		ans = 0
		for (d, p1, p2) in a:
			if union(p1, p2):
				ans += d
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if not points or len(points) <= 1:
			return 0
		p_dis = {}
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				p1 = points[i]
				p2 = points[j]
				dis = abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
				p_dis.setdefault(i, [])
				p_dis.setdefault(j, [])
				p_dis[i].append((dis, j))
				p_dis[j].append((dis, i))
		visited = [False] * len(points)
		visited[0] = True
		count = 1
		heap = []
		res = 0
		for (d, p) in p_dis[0]:
			heapq.heappush(heap, (d, p))
		while heap:
			(dis, p) = heapq.heappop(heap)
			if not visited[p]:
				count += 1
				visited[p] = True
				res += dis
				for (_d, _p) in p_dis[p]:
					heapq.heappush(heap, (_d, _p))
			if count == len(points):
				break
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		parents = [i for i in range(n)]

		def ufind(node):
			nonlocal parents
			if parents[node] == node:
				return node
			parents[node] = ufind(parents[node])
			return parents[node]

		def union(node1, node2):
			p1 = ufind(node1)
			p2 = ufind(node2)
			if p1 != p2:
				parents[p2] = p1

		def MST(edges):
			nonlocal n
			edges.sort(key=lambda x: x[2])
			ans = 0
			for i in edges:
				p1 = ufind(i[0])
				p2 = ufind(i[1])
				if p1 != p2:
					ans += i[2]
					union(p1, p2)
			return ans
		edges = []
		for i in range(n):
			for j in range(i + 1, n):
				edges.append((i, j, abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])))
		return MST(edges)


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		arr = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				(xi, yi) = points[i]
				(xj, yj) = points[j]
				arr.append([i, j, abs(xi - xj) + abs(yi - yj)])
		arr.sort(key=lambda x: x[2])
		visited = set()
		res = 0
		group = []
		for i in range(len(arr)):
			(u, v, d) = arr[i]
			if u not in visited and v not in visited:
				visited.add(u)
				visited.add(v)
				res += d
				group.append({u, v})
			elif u in visited and v in visited:
				for (idx, tmp) in enumerate(group):
					if u in tmp:
						ui = idx
					if v in tmp:
						vi = idx
				if ui != vi:
					group[ui].update(group[vi])
					group.pop(vi)
					res += d
			else:
				for (idx, tmp) in enumerate(group):
					if u in tmp:
						group[idx].add(v)
						break
					elif v in tmp:
						group[idx].add(u)
						break
				visited.add(u)
				visited.add(v)
				res += d
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		(n, res) = (len(points), 0)
		if n <= 1:
			return res
		dists = [(abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j) for i in range(n - 1) for j in range(i + 1, n)]
		dists.sort()
		parents = list(range(n))

		def find(c):
			prec = c
			while parents[c] != c:
				c = parents[c]
			union(prec, c)
			return c

		def union(src, dst):
			if src != dst:
				parents[src] = dst
		for (d, src, dst) in dists:
			(ps, pd) = (find(src), find(dst))
			if ps != pd:
				res += d
				union(ps, pd)
		return res


class DSU:

	def __init__(self, n):
		self.parent = [i for i in range(n)]
		self.rank = [0 for _ in range(n)]

	def find(self, i):
		if self.parent[i] == i:
			return i
		else:
			return self.find(self.parent[i])

	def union(self, i, j):
		(x, y) = (self.find(i), self.find(j))
		(rx, ry) = (self.rank[x], self.rank[y])
		if rx > ry:
			self.parent[y] = x
		elif rx < ry:
			self.parent[x] = y
		else:
			self.parent[y] = x
			self.rank[x] += 1

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		edges = []
		for i in range(n):
			for j in range(n):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				edges.append((i, j, dist))
		edges.sort(key=lambda x: x[2])
		d = DSU(n)
		e = 0
		i = 0
		ret = 0
		while e < n - 1:
			if d.find(edges[i][0]) != d.find(edges[i][1]):
				ret += edges[i][2]
				d.union(edges[i][0], edges[i][1])
				e += 1
			i += 1
		return ret


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		from collections import defaultdict
		graph = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				val = abs(abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]))
				graph.append([tuple(points[i]), tuple(points[j]), val])
		graph.sort(key=lambda x: x[-1])
		parent = {tuple(i): tuple(i) for i in points}

		def find(x):
			if parent[x] == x:
				return x
			parent[x] = find(parent[x])
			return parent[x]

		def union(x, y):
			(a, b) = (find(x), find(y))
			if a != b:
				parent[a] = b
				return True
			else:
				return False
		v = 0
		n = len(points)
		res = 0
		i = 0
		while v != n - 1:
			(a, b, dist) = graph[i]
			if union(a, b):
				res += dist
				v += 1
			i += 1
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		N = len(points)
		dist = {}
		(pair, mindist) = ((0, 0), math.inf)
		for i in range(N):
			for j in range(i + 1, N):
				d = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				dist[i, j] = dist[j, i] = d
				if d < mindist:
					(pair, mindist) = ((i, j), d)
		res = mindist
		mst = set(pair)
		other = set((i for i in range(N) if i not in mst))
		h = []
		for v in mst:
			for i in other:
				heapq.heappush(h, (dist[v, i], i))
		while len(mst) < N:
			(d, i) = heapq.heappop(h)
			if i not in mst:
				res += d
				mst.add(i)
				other.remove(i)
				for j in other:
					heapq.heappush(h, (dist[i, j], j))
		return res if N > 1 else 0


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) == 1:
			return 0
		points = sorted(points, key=lambda r: r[0])
		((x1, y1), (x2, y2)) = points[:2]
		cost = abs(x2 - x1) + abs(y2 - y1)
		if len(points) == 2:
			return cost
		n = len(points)
		d = []
		for (i, (x, y)) in enumerate(points[:-1]):
			for (j, (xj, yj)) in enumerate(points[i + 1:]):
				d.append([i, i + j + 1, abs(xj - x) + abs(yj - y)])
		connections = sorted(d, key=lambda r: r[2])
		parent = [i for i in range(n)]

		def find(x):
			if x != parent[x]:
				parent[x] = find(parent[x])
			return parent[x]
		(res, e, k) = (0, 0, 0)
		while e < n - 1:
			(u, v, w) = connections[k]
			k += 1
			(x, y) = (find(u - 1), find(v - 1))
			if x != y:
				e += 1
				res += w
				parent[x] = y
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)

		def dist(points, i, j):
			return abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
		a = collections.defaultdict(list)
		for i in range(n):
			for j in range(i + 1, n):
				d = dist(points, i, j)
				a[i].append((d, j))
				a[j].append((d, i))
		(ans, cnt, q, visited) = (0, 1, a[0], [0] * n)
		visited[0] = 1
		heapify(q)
		while q:
			(d, j) = heappop(q)
			if not visited[j]:
				visited[j] = 1
				cnt += 1
				ans += d
				for i in a[j]:
					heappush(q, i)
			if cnt >= n:
				break
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		@functools.lru_cache(None)
		def distance(i, j):
			return abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
		not_added = set([i for i in range(1, len(points))])
		distance_to_added = [math.inf for i in range(len(points))]
		i = 0
		res = 0
		while not_added:
			for j in not_added:
				distance_to_added[j] = min(distance_to_added[j], distance(i, j))
			while not_added:
				i = min(range(len(points)), key=lambda x: distance_to_added[x])
				if i in not_added:
					res += distance_to_added[i]
					not_added.remove(i)
					break
				distance_to_added[i] = math.inf
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		dis = [math.inf for i in range(n)]
		myset = set()
		myset.add(0)
		res = 0
		pt = points[0]
		for i in range(n - 1):
			for (idx, item) in enumerate(points):
				if idx in myset:
					continue
				else:
					dis[idx] = min(dis[idx], abs(pt[0] - item[0]) + abs(pt[1] - item[1]))
			mins = min(dis)
			res += mins
			cur = dis.index(mins)
			myset.add(cur)
			dis[cur] = math.inf
			pt = points[cur]
		return res


class DSU:

	def __init__(self, n):
		self.par = list(range(n))
		self.rnk = [0] * n

	def find(self, x):
		if self.par[x] != x:
			self.par[x] = self.find(self.par[x])
		return self.par[x]

	def union(self, x, y):
		(xr, yr) = (self.find(x), self.find(y))
		if xr == yr:
			return False
		if self.rnk[xr] < self.rnk[yr]:
			(xr, yr) = (yr, xr)
		if self.rnk[xr] == self.rnk[yr]:
			self.rnk[xr] += 1
		self.par[yr] = xr
		return True

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		N = len(points)

		def dist(i, j):
			return abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
		pq = [[dist(0, j), 0, j] for j in range(1, N)]
		heapq.heapify(pq)
		actives = {0}
		ans = 0
		while len(actives) != N:
			(d, u, v) = heapq.heappop(pq)
			if u not in actives or v not in actives:
				ans += d
				(node,) = {u, v} - actives
				actives.add(node)
				for nei in range(N):
					if nei not in actives:
						heapq.heappush(pq, [dist(node, nei), node, nei])
		return ans
		N = len(points)
		edges = []
		for u in range(N - 1):
			for v in range(u + 1, N):
				edges.append([u, v, abs(points[u][0] - points[v][0]) + abs(points[u][1] - points[v][1])])

		def MST():
			dsu = DSU(N)
			ans = 0
			for (u, v, w) in sorted(edges, key=lambda e: e[2]):
				if dsu.union(u, v):
					ans += w
			return ans
		return MST()


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		q = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				dis = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				q.append((dis, i, j))

		def find(x):
			if x != parent[x]:
				parent[x] = find(parent[x])
			return parent[x]

		def union(x, y):
			if size[x] > size[y]:
				size[x] += size[y]
				parent[y] = x
			else:
				size[y] += size[x]
				parent[x] = y
		n = len(points)
		parent = [i for i in range(n + 1)]
		size = [1 for _ in range(n + 1)]
		q.sort()
		res = 0
		count = 0
		for (w, u, v) in q:
			(rA, rB) = (find(u), find(v))
			if rA == rB:
				continue
			union(rA, rB)
			res += w
			count += 1
			if count == n:
				return res
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		N = len(points)
		graph = collections.defaultdict(list)
		for i in range(N):
			(x1, y1) = points[i]
			for j in range(i + 1):
				(x2, y2) = points[j]
				z = abs(x1 - x2) + abs(y1 - y2)
				graph[i].append((j, z))
				graph[j].append((i, z))
		heap = []
		visited = set()
		heapq.heappush(heap, (0, 1))
		total = 0
		while heap:
			(cost, node) = heapq.heappop(heap)
			if node in visited:
				continue
			visited.add(node)
			total += cost
			if len(visited) == N:
				return total
			for (nxt, c) in graph[node]:
				if nxt not in visited:
					heapq.heappush(heap, (c, nxt))
		return -1


class Solution:

	def find(self, x, parent):
		if parent[x] != x:
			parent[x] = self.find(parent[x], parent)
		return parent[x]

	def union(self, x, y, parent):
		(px, py) = (self.find(x, parent), self.find(y, parent))
		parent[py] = px

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		parent = []
		n = len(points)
		for i in range(n):
			parent.append(i)
		edges = []
		for i in range(len(points)):
			(x, y) = points[i]
			for j in range(i + 1, len(points)):
				(u, v) = points[j]
				edges.append([i, j, abs(x - u) + abs(y - v)])
		edges = sorted(edges, key=lambda x: x[2])
		cost = 0
		for i in range(len(edges)):
			(p1, p2, w) = edges[i]
			if self.find(p1, parent) != self.find(p2, parent):
				self.union(p1, p2, parent)
				cost += w
		return cost


class DSU:

	def __init__(self, arr):
		self.p = {}
		self.n = 0

	def add(self, u):
		self.p[u] = u
		self.n += 1

	def find(self, u):
		if self.p[u] != u:
			self.p[u] = self.find(self.p[u])
		return self.p[u]

	def union(self, x, y):
		self.p[self.find(x)] = self.find(y)
		self.n -= 1
from itertools import combinations

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		comb = list(combinations(points, 2))
		edges = []
		ans = 0
		for c in comb:
			d = abs(c[0][0] - c[1][0]) + abs(c[0][1] - c[1][1])
			edges.append((c, d))
		edges.sort(key=lambda x: x[1])
		s = []
		for p in points:
			p = tuple(p)
			t = set()
			t.add(p)
			s.append(t)
		print(s)
		for e in edges:
			u1 = -1
			u2 = -1
			for i in range(len(s)):
				if tuple(e[0][0]) in s[i]:
					u1 = i
				if tuple(e[0][1]) in s[i]:
					u2 = i
			if u1 != u2:
				s[u1] = s[u1] | s[u2]
				s.pop(u2)
				ans += e[1]
			if len(s) == 1:
				break
		return ans


class UnionFind:

	def __init__(self, n):
		self.parents = [i for i in range(n)]
		self.size = [1] * n

	def find(self, i):
		while i != self.parents[i]:
			self.parents[i] = self.parents[self.parents[i]]
			i = self.parents[i]
		return i

	def union(self, a, b):
		aPar = self.find(a)
		bPar = self.find(b)
		if aPar == bPar:
			return False
		if self.size[aPar] > self.size[bPar]:
			self.parents[bPar] = aPar
			self.size[aPar] += self.size[bPar]
		else:
			self.parents[aPar] = bPar
			self.size[bPar] += self.size[aPar]
		return True

	def getSize(self, a):
		return self.size[self.find(a)]

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def getDistance(a, b):
			return abs(a[0] - b[0]) + abs(a[1] - b[1])
		N = len(points)
		uf = UnionFind(N)
		edges = []
		for i in range(N):
			for j in range(i + 1, N):
				edges.append((getDistance(points[i], points[j]), i, j))
		edges.sort(key=lambda x: x[0])
		cost = 0
		seen = 0
		for (w, a, b) in edges:
			if uf.union(a, b):
				cost += w
				i += 1
				if seen == N:
					break
		return cost


class UnionFind:

	def __init__(self, n):
		self.leaders = [i for i in range(n)]
		self.ranks = [1 for i in range(n)]

	def find(self, x):
		if self.leaders[x] != x:
			self.leaders[x] = self.find(self.leaders[x])
		return self.leaders[x]

	def union(self, x, y):
		p = self.find(x)
		q = self.find(y)
		if p == q:
			return False
		if self.ranks[p] < self.ranks[q]:
			self.leaders[p] = q
		elif self.ranks[p] > self.ranks[q]:
			self.leaders[q] = p
		else:
			self.leaders[q] = p
			self.ranks[p] += 1
		return True

class Solution:

	def minCostConnectPoints(self, points):
		n = len(points)
		if n == 1:
			return 0
		edges = []
		dist = lambda p0, p1: abs(p1[0] - p0[0]) + abs(p1[1] - p0[1])
		for u in range(n):
			for v in range(u + 1, n):
				w = dist(points[u], points[v])
				edges.append([u, v, w])
		(res, cnt) = (0, 0)
		edges.sort(key=lambda x: x[2])
		uf = UnionFind(n + 1)
		for (u, v, w) in edges:
			if uf.union(u, v):
				res += w
				cnt += 1
			if cnt == n - 1:
				return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		d = [99999999] * n
		d[0] = 0
		added = set()
		ans = 0
		for i in range(n):
			j_min = -1
			d_min = 99999999
			for j in range(n):
				if j not in added:
					if d[j] < d_min:
						j_min = j
						d_min = d[j]
			added.add(j_min)
			ans += d_min
			for k in range(n):
				if k not in added:
					if abs(points[k][0] - points[j_min][0]) + abs(points[k][1] - points[j_min][1]) < d[k]:
						d[k] = abs(points[k][0] - points[j_min][0]) + abs(points[k][1] - points[j_min][1])
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		if n == 1:
			return 0
		edges = []
		for i in range(n):
			for j in range(i + 1, n):
				dis = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				edges.append((dis, i, j))
		UF = {i: i for i in range(n)}

		def find(i):
			if i != UF[i]:
				UF[i] = find(UF[i])
			return UF[i]

		def union(i, j):
			UF[find(i)] = find(j)
		ans = 0
		for (w, x, y) in sorted(edges):
			if find(x) != find(y):
				ans += w
				union(x, y)
		return ans


import sys

class Solution:

	def manhattan(self, p1, p2):
		cost = abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		return cost

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) == 1:
			return 0
		total_cost = 0
		connected = []
		edges = []
		for i in range(len(points)):
			connected.append(set([i]))
		if len(points) == 1:
			return 0
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				edges.append([i, j, self.manhattan(points[i], points[j])])
		edges = sorted(edges, key=lambda i: i[2])
		edge_counter = 0
		while len(connected) > 1:
			edge = edges[edge_counter]
			edge_counter += 1
			cycle = False
			for tree in connected:
				if edge[0] in tree and edge[1] in tree:
					cycle = True
					break
			if cycle == True:
				continue
			else:
				set1 = None
				index1 = None
				set2 = None
				index2 = None
				for i in range(len(connected)):
					sets = connected[i]
					if not set1 and edge[0] in sets:
						set1 = sets
						index1 = i
					if not set2 and edge[1] in sets:
						set2 = sets
						index2 = i
					if set1 and set2:
						break
				connected.append(set1.union(set2))
				del connected[max(index1, index2)]
				del connected[min(index1, index2)]
				total_cost += edge[2]
		return total_cost


from heapq import *

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		dist = []
		for i in range(len(points)):
			dist.append([])
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				d = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				dist[i].append((d, i, j))
				dist[j].append((d, j, i))
		visited = [False] * len(points)
		hq = []
		for x in dist[0]:
			heappush(hq, x)
		visited[0] = True
		cost = 0
		print(hq)
		while not all(visited):
			(d, i, j) = heappop(hq)
			if visited[i] and visited[j]:
				continue
			if visited[i] == False:
				ind = i
			else:
				ind = j
			visited[ind] = True
			cost += d
			for x in dist[ind]:
				if visited[x[1]] == False or visited[x[2]] == False:
					heappush(hq, x)
		return cost


import heapq

class Solution:

	def minCostConnectPoints_Prim(self, points: List[List[int]]) -> int:
		manhattan = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		(n, c) = (len(points), collections.defaultdict(list))
		for i in range(n):
			for j in range(i + 1, n):
				d = manhattan(points[i], points[j])
				c[i].append((d, j))
				c[j].append((d, i))
		visited = set()
		visited.add(0)
		res = 0
		heap = c[0]
		heapq.heapify(heap)
		while len(visited) < n:
			(d, j) = heapq.heappop(heap)
			if j not in visited:
				visited.add(j)
				res += d
				for record in c[j]:
					heapq.heappush(heap, record)
		return res

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		manhattan = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		n = len(points)
		edges = []
		for i in range(n):
			for j in range(i + 1, n):
				edges.append((manhattan(points[i], points[j]), i, j))
		edges.sort()
		res = 0
		ds = DisjointSet(n)
		for (cost, u, v) in edges:
			if ds.find(u) != ds.find(v):
				ds.union(u, v)
				res += cost
		return res

class DisjointSet:

	def __init__(self, n):
		self.parent = [i for i in range(n)]
		self.rank = [1 for _ in range(n)]

	def union(self, a, b):
		pa = self.find(a)
		pb = self.find(b)
		if pa == pb:
			return
		if self.rank[pa] > self.rank[pb]:
			self.parent[pb] = pa
			self.rank[pa] += self.rank[pb]
		else:
			self.parent[pa] = pb
			self.rank[pb] += self.rank[pa]

	def find(self, p):
		if self.parent[p] == p:
			return p
		self.parent[p] = self.find(self.parent[p])
		return self.parent[p]


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def heap_pop(h):
			res = h[0]
			h[0] = h[-1]
			h.pop()
			current = 0
			while 2 * current + 1 < len(h):
				child = 2 * current + 1
				if child + 1 < len(h):
					if h[child + 1][0] < h[child][0]:
						child += 1
				if h[current][0] <= h[child][0]:
					break
				(h[current], h[child]) = (h[child], h[current])
				current = child
			return res

		def heap_insert(h, val):
			current = len(h)
			h.append(val)
			while current > 0:
				p = (current - 1) // 2
				if h[p][0] <= h[current][0]:
					break
				(h[p], h[current]) = (h[current], h[p])
				current = p
		n = len(points)
		dp = [[0 for i in range(n)] for j in range(n)]
		for i in range(n):
			for j in range(n):
				dp[i][j] = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
		visited = [0 for i in range(n)]
		visited[0] = 1
		res = 0
		heap = [(dp[0][j], 0, j) for j in range(n)]
		heap.sort()
		heap.pop(0)
		while sum(visited) < n:
			(cost, _, current) = heap_pop(heap)
			if visited[current] == 1:
				continue
			visited[current] = 1
			res += cost
			for j in range(n):
				if visited[j] != 1 and j != current:
					heap_insert(heap, (dp[current][j], current, j))
		return res


from collections import defaultdict
from heapq import *

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		edges = []
		for (i, (x, y)) in enumerate(points):
			for (j, (h, k)) in enumerate(points):
				if j <= i:
					continue
				d = abs(x - h) + abs(y - k)
				edges.append((i, j, d))
		g = defaultdict(list)
		for e in edges:
			g[e[0]].append((e[1], e[2]))
			g[e[1]].append((e[0], e[2]))
		q = []
		cost = 0
		seen = set()
		heappush(q, (0, 0))
		for _ in range(n):
			while True:
				(w, u) = heappop(q)
				if u in seen:
					continue
				cost += w
				seen.add(u)
				for (v, w) in g[u]:
					if v in seen:
						continue
					heappush(q, (w, v))
				break
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) <= 1:
			return 0
		prior = [[] for _ in points]
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				prior[i].append((dist, j))
				prior[j].append((dist, i))
		heapify(prior[0])
		seen = set([0])
		cur = prior[0]
		res = 0
		while len(seen) < len(points):
			(dist, tar) = heappop(cur)
			if tar not in seen:
				res += dist
				seen.add(tar)
				for (d, t) in prior[tar]:
					if t not in seen:
						heappush(cur, (d, t))
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		nodes = len(points)
		edges = sorted([(abs(points[src][0] - points[dst][0]) + abs(points[src][1] - points[dst][1]), src, dst) for src in range(nodes) for dst in range(src + 1, nodes)])
		roots = [node for node in range(nodes)]

		def find(v):
			if roots[v] != v:
				roots[v] = find(roots[v])
			return roots[v]

		def union(u, v):
			(p1, p2) = (find(u), find(v))
			if p1 != p2:
				roots[p2] = roots[p1]
				return True
			return False
		return sum((distance for (distance, src, dst) in edges if union(src, dst)))


class DSU:

	def __init__(self, n):
		self.parent = list(range(n))
		self.size = [1] * n

	def find(self, x):
		if x != self.parent[x]:
			self.parent[x] = self.find(self.parent[x])
		return self.parent[x]

	def union(self, x, y):
		(xp, yp) = (self.find(x), self.find(y))
		if xp == yp:
			return False
		if self.size[xp] < self.size[yp]:
			(xp, yp) = (yp, xp)
		self.size[xp] += self.size[yp]
		self.parent[yp] = xp
		return True

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		dsu = DSU(len(points))
		ans = 0
		edges = []
		for (i, (xi, yi)) in enumerate(points):
			for j in range(i + 1, len(points)):
				(xj, yj) = points[j]
				edges.append((abs(xi - xj) + abs(yi - yj), i, j))
		edges.sort()
		ans = 0
		for (d, v1, v2) in edges:
			if dsu.find(v1) != dsu.find(v2):
				ans += d
				dsu.union(v1, v2)
		return ans


class Solution:

	def minCostConnectPoints(self, points):
		N = len(points)
		dist = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		connections = [[u, v, dist(points[u], points[v])] for u in range(N - 1) for v in range(u + 1, N)]
		connections.sort(key=lambda x: x[2])
		(parent, cnt, res) = ([i for i in range(N + 1)], N - 1, 0)

		def find(v):
			while parent[v] != parent[parent[v]]:
				parent[v] = parent[parent[v]]
			return parent[v]
		for (u, v, cost) in connections:
			(pu, pv) = (find(u), find(v))
			if pu != pv:
				parent[pu] = pv
				cnt -= 1
				res += cost
				if cnt == 0:
					break
		return res

class Solution:

	def minCostConnectPoints(self, points):
		distance = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		points.sort(key=lambda p: p[0] + p[1])
		total_cost = 0
		points = [[p, distance(p, points[0])] for p in points]
		while points:
			(minIdx, mindist) = (None, float('inf'))
			for (i, (p1, dist)) in enumerate(points):
				if dist < mindist:
					(minIdx, mindist) = (i, dist)
			(p1, cost) = points.pop(minIdx)
			total_cost += cost
			for (i, (p2, dist)) in enumerate(points):
				newdist = distance(p1, p2)
				if newdist < dist:
					points[i][1] = newdist
		return total_cost


class Solution:

	class Union:

		def __init__(self):
			self.collection = {}

		def get_head(self, i):
			if i not in self.collection:
				return (-1, 1)
			while i in self.collection and self.collection[i][0] != i:
				i = self.collection[i][0]
			return self.collection[i]

		def add(self, i, j):
			(head_i, cnt_i) = self.get_head(i)
			(head_j, cnt_j) = self.get_head(j)
			if head_i == head_j and head_i != -1:
				return (False, cnt_i)
			head = head_i if cnt_i >= cnt_j else head_j
			cnt = cnt_i + cnt_j
			if head == -1:
				head = i
			self.collection[head_i] = (head, cnt)
			self.collection[head_j] = (head, cnt)
			self.collection[i] = (head, cnt)
			self.collection[j] = (head, cnt)
			return (True, cnt)
	from heapq import heappush, heappop

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		heap = []
		union = Solution.Union()
		total = 0
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				val = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				heappush(heap, (val, i, j))
		while heap:
			(val, i, j) = heappop(heap)
			(added, cnt) = union.add(i, j)
			if added:
				total += val
			if cnt == len(points):
				break
		return total


def top(idx, i):
	(d, j) = (0, idx[i])
	while i != j:
		(i, j, d) = (j, idx[j], d + 1)
	return (j, d)

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		(best, idx) = (0, {i: i for i in range(len(points))})
		buf = [(abs(x1 - x2) + abs(y1 - y2), i1, i2) for (i1, (x1, y1)) in enumerate(points[:-1]) for (i2, (x2, y2)) in enumerate(points[i1 + 1:], i1 + 1)]
		for (now, i1, i2) in sorted(buf):
			(j1, d1) = top(idx, i1)
			(j2, d2) = top(idx, i2)
			if j1 == j2:
				continue
			best += now
			if d1 < d2:
				idx[i1] = idx[i2] = idx[j1] = j2
			else:
				idx[i1] = idx[i2] = idx[j2] = j1
		return best


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		graph = []
		self.parent = [i for i in range(len(points))]
		cost = 0
		self.N = len(points)
		for i in range(len(points) - 1):
			for j in range(len(points)):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				heapq.heappush(graph, [dist, i, j])
		while self.N > 1:
			(c, u, v) = heapq.heappop(graph)
			if u != v and self.union(u, v):
				cost += c
		return cost

	def union(self, x, y):
		parentX = self.find(x)
		parentY = self.find(y)
		if parentX == parentY:
			return False
		if self.parent[parentX] <= self.parent[parentY]:
			self.parent[parentY] = parentX
		else:
			self.parent[parentX] = parentY
		self.N -= 1
		return True

	def find(self, x):
		if self.parent[x] != x:
			self.parent[x] = self.find(self.parent[x])
		return self.parent[x]


class Solution(object):

	def minCostConnectPoints(self, points):
		g = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				g.append((i, j, abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])))
		g0 = sorted(g, key=lambda x: x[2])
		uf = UnionFind(len(points))
		ans = 0
		for (x, y, z) in g0:
			if uf.union(x, y):
				ans += z
		return ans

class UnionFind:

	def __init__(self, n):
		self.parents = [i for i in range(n)]

	def find(self, x):
		if self.parents[x] == x:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return False
		self.parents[y] = x
		return True


class DSU:

	def __init__(self, n):
		self.parent = [i for i in range(n)]
		self.rank = [0 for _ in range(n)]
		self.size = n

	def find(self, x):
		if self.parent[x] != x:
			self.parent[x] = self.find(self.parent[x])
		return self.parent[x]

	def union(self, x, y):
		(xp, yp) = (self.find(x), self.find(y))
		if xp == yp:
			return False
		if self.rank[xp] < self.rank[yp]:
			self.parent[xp] = yp
		elif self.rank[xp] > self.rank[yp]:
			self.parent[yp] = xp
		else:
			self.parent[xp] = yp
			self.rank[yp] += 1
		self.size -= 1
		return True

	def getSize(self):
		return self.size

class Solution:
	import heapq

	def minCostConnectPoints1(self, points: List[List[int]]) -> int:

		def getDist(i, j):
			return abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
		(heap, n, visited, res) = ([], len(points), set([0]), 0)
		for i in range(1, n):
			heapq.heappush(heap, (getDist(0, i), (0, i)))
		while len(visited) < n:
			(dist, (i, j)) = heapq.heappop(heap)
			if j not in visited:
				visited.add(j)
				res += dist
				for k in range(n):
					if k not in visited:
						heapq.heappush(heap, (getDist(j, k), (j, k)))
		return res

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		graph = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				graph.append((i, j, abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])))
		graph.sort(key=lambda x: x[2])
		dsu = DSU(len(points) + 1)
		res = 0
		for (i, j, cost) in graph:
			if dsu.union(i, j):
				res += cost
		return res


def dist(p1, p2):
	return int(abs(p1[0] - p2[0]) + abs(p1[1] - p2[1]))

def find(x, uf):
	if uf[x] == x:
		return x
	uf[x] = find(uf[x], uf)
	return uf[x]

def union(x, y, uf):
	xx = find(x, uf)
	yy = find(y, uf)
	if xx == yy:
		return False
	uf[xx] = yy
	return True

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		edges = []
		for i in range(n):
			for j in range(i + 1, n):
				edges.append((dist(points[i], points[j]), i, j))
		edges.sort()
		uf = list(range(n))
		ans = 0
		for e in edges:
			if union(e[1], e[2], uf):
				ans += e[0]
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		N = len(points)
		edge_list = []
		for i in range(N):
			(x0, y0) = points[i]
			for j in range(i + 1, N):
				(x1, y1) = points[j]
				mh = abs(x1 - x0) + abs(y1 - y0)
				edge_list.append((mh, i, j))
		edge_list.sort()
		edge_count = 0
		val = 0
		uf = UnionFind(N)
		while edge_count != N - 1:
			(mh, i, j) = edge_list.pop(0)
			if uf.union(i, j):
				val += mh
				edge_count += 1
		return val

class UnionFind:

	def __init__(self, n):
		self.parents = {i: i for i in range(0, n)}
		self.groups = n

	def find(self, x):
		if self.parents[x] == x:
			return x
		else:
			self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

	def union(self, x, y):
		x = self.find(x)
		y = self.find(y)
		if x == y:
			return False
		self.parents[y] = x
		self.groups -= 1
		return True


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		edges = []
		for i in range(n):
			for j in range(i + 1, n):
				d = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				edges.append((d, i, j))
		edges.sort()
		roots = [i for i in range(n)]

		def find(v):
			if roots[v] != v:
				roots[v] = find(roots[v])
			return roots[v]

		def union(u, v):
			p1 = find(u)
			p2 = find(v)
			if p1 != p2:
				roots[p2] = roots[p1]
				return True
			return False
		res = 0
		for (d, u, v) in edges:
			if union(u, v):
				res += d
		return res


class Solution:

	def minCostConnectPoints(self, p: List[List[int]]) -> int:

		class DSU:

			def __init__(self, n):
				self.parent = list(range(n))
				self.size = [1] * n

			def find(self, x):
				if self.parent[x] != x:
					self.parent[x] = self.find(self.parent[x])
				return self.parent[x]

			def unite(self, x, y):
				(px, py) = (self.find(x), self.find(y))
				if px == py:
					return False
				if self.size[px] > self.size[py]:
					(px, py) = (py, px)
				self.size[py] += self.size[px]
				self.parent[px] = py
				return True
		n = len(p)
		total = 0
		dsu = DSU(n)
		edges = []
		for x in range(1, n):
			for y in range(x):
				edges.append((x, y, abs(p[x][0] - p[y][0]) + abs(p[x][1] - p[y][1])))
		edges.sort(key=lambda x: x[2])
		for (x, y, cost) in edges:
			if dsu.unite(x, y):
				total += cost
		return total


from collections import defaultdict

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def calc_distance(p1, p2):
			(x1, y1) = p1
			(x2, y2) = p2
			return abs(x1 - x2) + abs(y1 - y2)

		def find_best_node(min_dists, mst_set):
			min_dist = float('inf')
			for (i, dist) in enumerate(min_dists):
				if i not in mst_set and dist < min_dist:
					best_node = i
					min_dist = dist
			return (best_node, min_dist)

		def update_min_dists(node, min_dists, graph):
			for (i, dist) in graph[node]:
				min_dists[i] = min(min_dists[i], dist)
		n = len(points)
		if n <= 1:
			return 0
		graph = defaultdict(list)
		for i in range(n):
			for j in range(i + 1, n):
				(p1, p2) = (points[i], points[j])
				dist = calc_distance(p1, p2)
				graph[i].append((j, dist))
				graph[j].append((i, dist))
		min_dists = [float('inf') for _ in range(n)]
		mst_set = {0}
		for (i, dist) in graph[0]:
			min_dists[i] = min(min_dists[i], dist)
		total_dist = 0
		for _ in range(n - 1):
			(best_node, min_dist) = find_best_node(min_dists, mst_set)
			mst_set.add(best_node)
			update_min_dists(best_node, min_dists, graph)
			total_dist += min_dist
		return total_dist


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def find(a):
			if a != root[a]:
				root[a] = find(root[a])
			return root[a]

		def union(a, b):
			(a, b) = (find(a), find(b))
			if a == b:
				return 0
			root[a] = b
			return 1
		root = [i for i in range(len(points))]
		res = 0
		edges = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				(a, b) = points[i]
				(c, d) = points[j]
				edges.append([abs(a - c) + abs(b - d), i, j])
		edges.sort()
		us = 0
		while us != len(points) - 1:
			(dis, i, j) = edges.pop(0)
			if union(i, j):
				res += dis
				us += 1
		return res


class Solution:

	def minCostConnectPoints(self, A: List[List[int]]) -> int:
		N = len(A)
		P = [i for i in range(N)]
		E = []
		for u in range(N):
			(x1, y1) = A[u]
			for v in range(u + 1, N):
				(x2, y2) = A[v]
				w = abs(x1 - x2) + abs(y1 - y2)
				E.append([u, v, w])
		E.sort(key=lambda edge: edge[2])

		def find(x):
			P[x] = P[x] if P[x] == x else find(P[x])
			return P[x]

		def union(a, b):
			a = find(a)
			b = find(b)
			if a == b:
				return False
			P[a] = b
			return True
		return sum([w for (u, v, w) in E if union(u, v)])


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) == 1:
			return 0

		def distance(p1, p2):
			return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		n = len(points)
		parents = list(range(n))

		def find(x):
			if x != parents[x]:
				parents[x] = find(parents[x])
			return parents[x]

		def union(x, y):
			(px, py) = (find(x), find(y))
			if px != py:
				parents[py] = px
				return True
			return False
		ans = 0
		count = 0
		g = []
		for i in range(n):
			for j in range(i + 1, n):
				cost = distance(points[i], points[j])
				g.append([cost, i, j])
		for (cost, pt1, pt2) in sorted(g):
			if union(pt1, pt2):
				ans += cost
				count += 1
			if count == n - 1:
				return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def method1():

			class UF:

				def __init__(self, size):
					self.p = list(range(size))
					self.rank = [1] * size

				def find(self, x):
					if x != self.p[x]:
						self.p[x] = self.find(self.p[x])
					return self.p[x]

				def union(self, x, y):
					px = self.find(x)
					py = self.find(y)
					if self.rank[px] < self.rank[py]:
						(px, py) = (py, px)
					self.p[px] = py
					if self.rank[px] == self.rank[py]:
						self.rank[px] += 1
			edges = []
			n = len(points)
			for i in range(n - 1):
				for j in range(i + 1, n):
					dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
					edges.append((dist, i, j))
			edges.sort()
			uf = UF(n)
			res = 0
			for (cost, u, v) in edges:
				if uf.find(u) != uf.find(v):
					uf.union(u, v)
					res += cost
			return res
		return method1()


class Solution:

	def find(self, par, x):
		if par[x] == x:
			return x
		else:
			par[x] = self.find(par, par[x])
			return par[x]

	def merge(self, par, x, y):
		x = self.find(par, x)
		y = self.find(par, y)
		if x == y:
			return False
		par[x] = y
		return True

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		par = [i for i in range(len(points))]
		dis = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		edges = []
		visited = set()
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				edges.append((dis(points[i], points[j]), i, j))
		edges.sort()
		r = 0
		for (d, i, j) in edges:
			if self.merge(par, i, j):
				r += d
		return r


import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		l = len(points)
		stc = []
		heapq.heapify(stc)
		cost = 0
		self.parent = [-1 for i in range(l)]

		def find(a):
			if self.parent[a] < 0:
				print(('a ', a))
				return a
			else:
				return find(self.parent[a])

		def union(a, b):
			u = find(a)
			v = find(b)
			if u == v:
				return False
			else:
				if abs(self.parent[u]) >= abs(self.parent[v]):
					self.parent[u] += self.parent[v]
					self.parent[v] = u
				else:
					self.parent[v] += self.parent[u]
					self.parent[u] = v
				return True
		for i in range(l):
			for j in range(l):
				if i != j:
					heapq.heappush(stc, [abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j])
		edge = 0
		while edge < l - 1:
			t = heapq.heappop(stc)
			y = union(t[1], t[2])
			if y == True:
				cost += t[0]
				edge += 1
		return cost


class Node:

	def __init__(self, val):
		self.val = val
		self.next = None
		self.parent = None

class Component:

	def __init__(self):
		self.length = 0
		self.head = None
		self.tail = None

class Solution:

	def __init__(self):
		self.ds = {}

	def findSet(self, key):
		if key in self.ds:
			return self.ds[key]
		node = Node(key)
		component = Component()
		node.parent = component
		component.head = node
		component.tail = node
		component.length += 1
		self.ds[key] = component
		return component

	def unionSet(self, c1, c2):
		if c1.length < c2.length:
			(c1, c2) = (c2, c1)
		c1.tail.next = c2.head
		c1.tail = c2.tail
		tmp = c2.head
		while tmp:
			tmp.parent = c1
			self.ds[tmp.val] = c1
			tmp = tmp.__next__
		c1.length += c2.length

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		edges = []
		for i in range(n):
			j = i + 1
			while j < n:
				edges.append((i, j, abs(abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]))))
				j += 1
		edges.sort(key=lambda x: x[2])
		cost = 0
		for edge in edges:
			c1 = self.findSet(edge[0])
			c2 = self.findSet(edge[1])
			if c1 != c2:
				self.unionSet(c1, c2)
				cost += edge[2]
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)

		def distance(p1, p2):
			return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		sets = [i for i in range(n + 1)]

		def find(i):
			if i != sets[i]:
				sets[i] = find(sets[i])
			return sets[i]

		def union(x, y):
			(x, y) = (find(x), find(y))
			if x == y:
				return 0
			sets[x] = y
			return 1
		edges = []
		for i in range(n):
			for j in range(i + 1, n):
				edges.append([distance(points[i], points[j]), i, j])
		edges.sort(key=lambda x: x[0])
		weight = 0
		for (w, i, j) in edges:
			if union(i, j):
				weight += w
		return weight


import sys
input = sys.stdin.readline

class Unionfind:

	def __init__(self, n):
		self.par = [-1] * n
		self.rank = [1] * n

	def root(self, x):
		r = x
		while not self.par[r] < 0:
			r = self.par[r]
		t = x
		while t != r:
			tmp = t
			t = self.par[t]
			self.par[tmp] = r
		return r

	def unite(self, x, y):
		rx = self.root(x)
		ry = self.root(y)
		if rx == ry:
			return
		if self.rank[rx] <= self.rank[ry]:
			self.par[ry] += self.par[rx]
			self.par[rx] = ry
			if self.rank[rx] == self.rank[ry]:
				self.rank[ry] += 1
		else:
			self.par[rx] += self.par[ry]
			self.par[ry] = rx

	def is_same(self, x, y):
		return self.root(x) == self.root(y)

	def count(self, x):
		return -self.par[self.root(x)]

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []
		for i in range(len(points)):
			(xi, yi) = points[i]
			for j in range(i + 1, len(points)):
				(xj, yj) = points[j]
				edges.append((abs(xi - xj) + abs(yi - yj), i, j))
		edges.sort()
		uf = Unionfind(len(points))
		ans = 0
		for (w, u, v) in edges:
			if not uf.is_same(u, v):
				ans += w
				uf.unite(u, v)
		return ans


class UF:

	def __init__(self, n):
		self.parent = [i for i in range(n)]
		self.size = [1 for i in range(n)]

	def find(self, a):
		while self.parent[a] != a:
			self.parent[a] = self.parent[self.parent[a]]
			a = self.parent[a]
		return a

	def isConnected(self, a, b):
		return self.find(a) == self.find(b)

	def union(self, a, b):
		parentA = self.find(a)
		parentB = self.find(b)
		if self.isConnected(a, b):
			return
		if self.size[parentA] > self.size[parentB]:
			self.parent[parentB] = parentA
			self.size[parentA] += self.size[parentB]
		else:
			self.parent[parentA] = parentB
			self.size[parentB] += self.size[parentA]

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []
		n = len(points)
		for i in range(n):
			for j in range(i + 1, n):
				manhattanDist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				edges.append((manhattanDist, i, j))
		edges.sort()
		res = 0
		uf = UF(n)
		for (cost, i, j) in edges:
			if not uf.isConnected(i, j):
				uf.union(i, j)
				res += cost
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		dsu = [i for i in range(n)]

		def get_root(id: int):
			dsu[id] = id if dsu[id] == id else get_root(dsu[id])
			return dsu[id]

		def unite(a: int, b: int) -> bool:
			a = get_root(a)
			b = get_root(b)
			if a == b:
				return False
			dsu[a] = b
			return True
		e = []
		for i in range(n):
			for j in range(i + 1, n):
				e.append([i, j, abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])])
		e.sort(key=lambda edge: edge[2])
		return sum([edge[2] for edge in e if unite(edge[0], edge[1])])


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		costs = []
		ans = 0
		for (i, node_x) in enumerate(points):
			for (j, node_y) in enumerate(points):
				if i != j:
					costs.append((abs(node_x[0] - node_y[0]) + abs(node_x[1] - node_y[1]), i, j))
		costs.sort()

		def get_fa(i):
			if fa[i] != i:
				fa[i] = get_fa(fa[i])
			return fa[i]
		fa = list(range(len(points)))
		count = 0
		for (v, i, j) in costs:
			if get_fa(i) != get_fa(j):
				ans += v
				fa[fa[i]] = fa[j]
				count += 1
				if count == len(points) - 1:
					return ans
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		if n <= 1:
			return 0
		edges = []
		for (i, coor) in enumerate(points):
			(x1, y1) = coor
			for j in range(i + 1, n):
				(x2, y2) = points[j]
				edges.append((abs(x1 - x2) + abs(y1 - y2), i, j))
		root = [i for i in range(n)]

		def union(p, q):
			(r1, r2) = (find(p), find(q))
			if r1 != r2:
				root[r1] = r2
				return False
			return True

		def find(p):
			if p == root[p]:
				return p
			root[p] = find(root[p])
			return root[p]
		distance = 0
		for (d, p1, p2) in sorted(edges):
			if not union(p1, p2):
				distance += d
		return distance


from collections import defaultdict
import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def manhattan(x, y):
			return abs(x[0] - y[0]) + abs(x[1] - y[1])
		dist_dict = defaultdict(list)
		n_points = len(points)
		for i in range(n_points):
			for j in range(i + 1, n_points):
				dist_curr = manhattan(points[i], points[j])
				dist_dict[i].append((dist_curr, j))
				dist_dict[j].append((dist_curr, i))
		total_dist = 0
		visited = [False] * n_points
		counter = 1
		dist_heap = dist_dict[0]
		heapq.heapify(dist_heap)
		visited[0] = True
		while dist_heap:
			(dist_curr, point_curr) = heapq.heappop(dist_heap)
			if not visited[point_curr]:
				visited[point_curr] = True
				for neighbor in dist_dict[point_curr]:
					heapq.heappush(dist_heap, neighbor)
				total_dist += dist_curr
				counter += 1
			if counter >= n_points:
				break
		return total_dist


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		num_points = len(points)
		pairwise_dist = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				pairwise_dist.append([abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j])
		pairwise_dist.sort(key=lambda x: x[0])
		distance = 0
		par = list(range(num_points))
		rank = [0] * num_points

		def find(node):
			if par[node] != node:
				par[node] = find(par[node])
			return par[node]

		def union(x, y):
			par_x = find(x)
			par_y = find(y)
			if rank[par_x] > rank[par_y]:
				par[par_y] = par_x
			elif rank[par_x] < rank[par_y]:
				par[par_x] = par_y
			else:
				par[par_x] = par_y
				rank[par_y] += 1
		for pair in pairwise_dist:
			if find(pair[1]) == find(pair[2]):
				continue
			distance += pair[0]
			union(pair[1], pair[2])
		return distance


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		from collections import defaultdict
		import heapq
		manhattan = lambda a, b: abs(a[0] - b[0]) + abs(a[1] - b[1])
		(n, c) = (len(points), defaultdict(list))
		if n == 0:
			return 0
		for i in range(n):
			for j in range(i + 1, n):
				dis = manhattan(points[i], points[j])
				c[i].append((dis, j))
				c[j].append((dis, i))
		(cnt, ans, visited, heap) = (1, 0, [0] * n, c[0])
		visited[0] = 1
		heapq.heapify(heap)
		while cnt < n:
			(dis, p) = heapq.heappop(heap)
			if not visited[p]:
				(visited[p], cnt, ans) = (1, cnt + 1, ans + dis)
				for record in c[p]:
					heapq.heappush(heap, record)
		return ans


class UF(object):

	def __init__(self, size):
		self.parent = [i for i in range(size)]
		self.size = [1] * size

	def union(self, p, q):
		rootp = self.find(p)
		rootq = self.find(q)
		if rootq == rootp:
			return
		if self.size[rootp] > self.size[rootq]:
			self.parent[rootq] = rootp
			self.size[rootp] += self.size[rootq]
		else:
			self.parent[rootp] = rootq
			self.size[rootq] += self.size[rootp]

	def connected(self, p, q):
		rootp = self.find(p)
		rootq = self.find(q)
		return rootp == rootq

	def find(self, x):
		while self.parent[x] != x:
			self.parent[x] = self.parent[self.parent[x]]
			x = self.parent[x]
		return x

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		distances = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				distance = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				distances.append((distance, i, j))
		distances.sort()
		uf = UF(len(points))
		res = 0
		for (dis, u, v) in distances:
			if not uf.connected(u, v):
				uf.union(u, v)
				res += dis
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)

		def dist(points, i, j):
			return abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
		visited = [(0, (0, 0))]
		(ans, n) = (0, len(points))
		seen = set()
		while len(seen) < n:
			(d, (u, v)) = heappop(visited)
			if u in seen and v in seen:
				continue
			ans += d
			seen.add(v)
			for j in range(n):
				if j not in seen and j != v:
					heappush(visited, (dist(points, j, v), (v, j)))
		return ans


class Solution:

	class Union:

		def __init__(self, n):
			self.collection = [(i, 1) for i in range(n)]
			self.max_cnt = 0
			self.size = n

		def get_head(self, i):
			if self.collection[i][0] != i:
				return self.get_head(self.collection[i][0])
			return self.collection[i]

		def add(self, i, j):
			(head_i, cnt_i) = self.get_head(i)
			(head_j, cnt_j) = self.get_head(j)
			if head_i == head_j:
				return (False, self.max_cnt == self.size)
			head = head_i if cnt_i >= cnt_j else head_j
			cnt = cnt_i + cnt_j
			for x in [head_i, head_j, i, j]:
				self.collection[x] = (head, cnt)
			self.max_cnt = max(self.max_cnt, cnt)
			return (True, self.max_cnt == self.size)
	from heapq import heappush, heappop

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		heap = []
		union = Solution.Union(len(points))
		total = 0
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				val = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				heappush(heap, (val, i, j))
		while heap:
			(val, i, j) = heappop(heap)
			(x, y) = union.add(i, j)
			if x:
				total += val
			if y:
				break
		return total


class DSU:

	def __init__(self, n):
		self.p = [i for i in range(n)]

	def find(self, u):
		if self.p[u] != u:
			self.p[u] = self.find(self.p[u])
		return self.p[u]

	def union(self, x, y):
		self.p[self.find(x)] = self.find(y)
from collections import defaultdict

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		edges = []
		for i in range(n):
			for j in range(i + 1, n):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				edges.append((dist, i, j))
		edges.sort()
		res = 0
		ds = DSU(n)
		for (cost, u, v) in edges:
			if ds.find(u) != ds.find(v):
				ds.union(u, v)
				res += cost
		return res


class DSU:

	def __init__(self, n):
		self.p = list(range(n))
		self.r = [0] * n

	def find(self, i):
		if self.p[i] != i:
			self.p[i] = self.find(self.p[i])
		return self.p[i]

	def union(self, i, j):
		(pi, pj) = (self.find(i), self.find(j))
		if pi != pj:
			if self.r[pi] >= self.r[pj]:
				self.p[pj] = pi
				self.r[pi] += self.r[pi] == self.r[pj]
			else:
				self.p[pi] = pj
			return True
		return False

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		to_visit = set(range(1, len(points)))
		pq = [(abs(points[0][0] - points[x][0]) + abs(points[0][1] - points[x][1]), x) for x in range(1, len(points))]
		heapq.heapify(pq)
		ans = 0
		while pq:
			(cost, to) = heapq.heappop(pq)
			if to in to_visit:
				to_visit.remove(to)
				ans += cost
				for nei in to_visit:
					(x, y) = points[nei]
					heapq.heappush(pq, (abs(x - points[to][0]) + abs(y - points[to][1]), nei))
		return ans

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = [(abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j) for i in range(len(points)) for j in range(i + 1, len(points))]
		edges.sort()
		ans = 0
		uf = DSU(len(points))
		for (cost, i, j) in edges:
			if uf.find(i) != uf.find(j):
				uf.union(i, j)
				ans += cost
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		return self.prim(points)

	def generategraph(self, points):
		adjList = defaultdict(list)
		for p in points:
			for q in points:
				if p == q:
					continue
				adjList[p[0], p[1]].append((abs(p[0] - q[0]) + abs(p[1] - q[1]), (q[0], q[1])))
		return adjList

	def prim(self, points):
		if len(points) <= 1:
			return 0
		adjList = self.generategraph(points)
		visited = set()
		minCost = 0
		heap = [(0, tuple(points[0]), tuple(points[0]))]
		print(heap)
		while heap and len(visited) < len(points):
			(cost, u, v) = heapq.heappop(heap)
			if v in visited:
				continue
			minCost += cost
			visited.add(v)
			for (costNei, nei) in adjList[v]:
				if nei in visited:
					continue
				heapq.heappush(heap, (costNei, v, nei))
		return minCost


class Solution:

	def kruskal(self, n, edges):

		def find(x):
			if x != parent[x]:
				parent[x] = find(parent[x])
			return parent[x]

		def union(x, y):
			(px, py) = (find(x), find(y))
			if px == py:
				return (False, False)
			parent[px] = py
			rank[py] += rank[px]
			return (True, True) if rank[py] == n else (True, False)
		mst_cost = 0
		parent = list(range(n))
		rank = [0] * n
		for (f, t, w) in edges:
			(isUnion, isEnd) = union(f, t)
			if isUnion:
				mst_cost += w
			if isEnd:
				break
		return mst_cost

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		manhattan = lambda xx, yy: abs(xx[0] - yy[0]) + abs(xx[1] - yy[1])
		if (n := len(points)) == 1:
			return 0
		edges = []
		for i in range(n):
			for j in range(i + 1, n):
				(x, y) = (points[i], points[j])
				edges.append([i, j, manhattan(x, y)])
		edges.sort(key=lambda x: x[2])
		return self.kruskal(n, edges)


class UnionFind:

	def __init__(self, n):
		self.parents = [i for i in range(n)]
		self.rank = [1 for i in range(n)]

	def union(self, x, y):
		(a, b) = (self.find(x), self.find(y))
		if a == b:
			return
		if self.rank[a] > self.rank[b]:
			self.parents[b] = self.parents[a]
			self.rank[a] += self.rank[b]
		else:
			self.parents[a] = self.parents[b]
			self.rank[b] += self.rank[a]

	def find(self, x):
		if self.parents[x] != x:
			self.parents[x] = self.find(self.parents[x])
		return self.parents[x]

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []
		UF = UnionFind(len(points))
		cost = 0
		for i in range(len(points) - 1):
			for j in range(i + 1, len(points)):
				edges.append([abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j])
		edges.sort(key=lambda x: x[0])
		for i in range(len(edges)):
			(dist, j, k) = edges[i]
			if UF.find(j) != UF.find(k):
				cost += dist
				UF.union(j, k)
		return cost


class UnionFind:

	def __init__(self, length):
		self.parents = [-1] * length
		self.ranks = [1] * length

	def find(self, src):
		if self.parents[src] == -1:
			return src
		self.parents[src] = self.find(self.parents[src])
		return self.parents[src]

	def union(self, src, dest):
		(rootSrc, rootDest) = (self.find(src), self.find(dest))
		if rootSrc == rootDest:
			return False
		if self.ranks[rootSrc] > self.ranks[rootDest]:
			self.parents[rootDest] = rootSrc
			self.ranks[rootSrc] += self.ranks[rootDest]
			return True
		else:
			self.parents[rootSrc] = rootDest
			self.ranks[rootDest] += self.ranks[rootSrc]
			return True

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def calHamming(pt1, pt2):
			return abs(pt1[0] - pt2[0]) + abs(pt1[1] - pt2[1])
		ptsDistance = []
		for (i, j) in itertools.combinations(range(len(points)), 2):
			ptsDistance.append((calHamming(points[i], points[j]), i, j))
		ptsDistance.sort()
		result = 0
		uf = UnionFind(len(points))
		for (distance, src, dest) in ptsDistance:
			if uf.union(src, dest):
				result += distance
		return result


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def find(i):
			while i != root[i]:
				root[i] = root[root[i]]
				i = root[i]
			return i

		def union(i, j):
			if rank[i] < rank[j]:
				root[i] = j
			elif rank[i] > rank[j]:
				root[j] = i
			else:
				root[j] = i
				rank[i] += 1
		n = len(points)
		graph = []
		for i in range(n):
			for j in range(i + 1, n):
				distance = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				graph.append((distance, i, j))
		graph.sort()
		min_cost = 0
		root = list(range(n))
		rank = [0] * n
		for (distance, i, j) in graph:
			(root1, root2) = (find(i), find(j))
			if root1 != root2:
				union(root1, root2)
				min_cost += distance
		return min_cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		graph = collections.defaultdict(list)
		for (node1, points1) in enumerate(points):
			for (node2, points2) in enumerate(points):
				graph[node1].append((abs(points1[0] - points2[0]) + abs(points1[1] - points2[1]), node2))
		pq = [(0, 0)]
		res = 0
		visited = set()
		while pq:
			(d, node) = heapq.heappop(pq)
			if node in visited:
				continue
			visited.add(node)
			res += d
			if len(visited) == len(points):
				return res
			for (distance, nei) in graph[node]:
				if nei not in visited:
					heapq.heappush(pq, (distance, nei))
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		N = len(points)
		edges = []
		for i in range(N):
			a = tuple(points[i])
			for j in range(N):
				if i == j:
					continue
				b = tuple(points[j])
				cost = abs(a[0] - b[0]) + abs(a[1] - b[1])
				edges.append((cost, i, j))
		edges.sort()
		dsu = DSU(N)
		mst = 0
		count = 0
		for (cost, a, b) in edges:
			if count >= N - 1:
				break
			if dsu.union(a, b):
				mst += cost
				count += 1
		return mst

class DSU:

	def __init__(self, n):
		self.parent = [i for i in range(n)]
		self.size = [1 for _ in range(n)]

	def union(self, a, b):
		roota = self.find(a)
		rootb = self.find(b)
		if roota == rootb:
			return False
		if self.size[roota] < self.size[rootb]:
			self.size[rootb] += self.size[roota]
			self.parent[roota] = rootb
		else:
			self.size[roota] += self.size[rootb]
			self.parent[rootb] = roota
		return True

	def find(self, a):
		root = self.parent[a]
		while root != self.parent[root]:
			root = self.parent[root]
		curr = a
		while curr != root:
			after = self.parent[curr]
			self.parent[curr] = root
			curr = after
		return root


class UnionFind:

	def __init__(self, n):
		self.parent = collections.defaultdict(int)
		for i in range(1, n + 1):
			self.parent[i] = i

	def find(self, i):
		if i != self.parent[i]:
			self.parent[i] = self.find(self.parent[i])
		return self.parent[i]

	def union(self, u, v):
		(u_parent, v_parent) = (self.find(u), self.find(v))
		if u_parent == v_parent:
			return False
		self.parent[u_parent] = v_parent
		return True

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		connections = list()
		for i in range(n - 1):
			for j in range(i + 1, n):
				connections.append((i, j, abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])))
		res = 0
		connections_sorted = sorted(connections, key=lambda arr: arr[2])
		UF = UnionFind(n)
		for connection in connections_sorted:
			(a, b, cost) = connection
			if UF.find(a) != UF.find(b):
				UF.union(a, b)
				res += cost
		return res


from collections import defaultdict

class UnionFind:

	def __init__(self, n: int):
		self.n = list(range(n))

	def root(self, element: int):
		root = self.n[element]
		while root != self.n[root]:
			root = self.n[root]
		temp = self.n[element]
		while temp != self.n[temp]:
			self.n[temp] = root
			temp = self.n[temp]
		return root

	def union(self, a: int, b: int):
		rootA = self.root(a)
		rootB = self.root(b)
		self.n[rootB] = rootA

	def find(self, a: int, b: int):
		return self.root(a) == self.root(b)

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) < 2:
			return 0
		graph = defaultdict(list)
		edges = []
		for i in range(len(points)):
			(xi, yi) = points[i]
			for j in range(i + 1, len(points)):
				(xj, yj) = points[j]
				edges.append((abs(xi - xj) + abs(yi - yj), i, j))
		edges.sort()
		total = 0
		uf = UnionFind(len(points))
		for (distance, origin, destination) in edges:
			if not uf.find(origin, destination):
				uf.union(origin, destination)
				total += distance
		return total


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		G = collections.defaultdict(list)
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				dis = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				G[i].append((dis, j))
				G[j].append((dis, i))
		visited = {0}
		pq = G[0]
		heapq.heapify(pq)
		res = 0
		while len(visited) < len(points) and pq:
			(w, v) = heapq.heappop(pq)
			if v not in visited:
				res += w
				visited.add(v)
				for (w, nei) in G[v]:
					if nei not in visited:
						heapq.heappush(pq, (w, nei))
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		(N, g) = (len(points), [])
		res = 0
		for i in range(N - 1):
			(x0, y0) = points[i]
			for j in range(i + 1, N):
				(x1, y1) = points[j]
				dist = abs(x0 - x1) + abs(y0 - y1)
				g.append((dist, (i, j)))
		g.sort()
		parents = [None] * N
		for i in range(N):
			parents[i] = i

		def findParent(x):
			if parents[x] != x:
				parents[x] = findParent(parents[x])
			return parents[x]
		used_edges = 0
		for (w, (a, b)) in g:
			pa = findParent(a)
			pb = findParent(b)
			if pa != pb:
				res += w
				parents[pa] = pb
				used_edges += 1
				if used_edges == N - 1:
					break
		return res


class UnionFind(object):

	def __init__(self, n):
		self.par = [i for i in range(n)]
		self.rnk = [0] * n

	def find(self, x):
		if self.par[x] != x:
			self.par[x] = self.find(self.par[x])
		return self.par[x]

	def union(self, x, y):
		(xr, yr) = (self.find(x), self.find(y))
		if xr == yr:
			return False
		elif self.rnk[xr] < self.rnk[yr]:
			self.par[xr] = yr
		elif self.rnk[xr] > self.rnk[yr]:
			self.par[yr] = xr
		else:
			self.par[yr] = xr
			self.rnk[xr] += 1
		return True

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		distances = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				distances.append([i, j, abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])])
		distances.sort(key=lambda x: x[2])
		res = 0
		uf = UnionFind(n)
		for (i, j, d) in distances:
			if uf.find(i) == uf.find(j):
				continue
			res += d
			uf.union(i, j)
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def cost(a, b):
			return abs(a[0] - b[0]) + abs(a[1] - b[1])
		edges = [[] for _ in points]
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				dist = cost(points[i], points[j])
				edges[i].append([dist, j])
				edges[j].append([dist, i])
		cost = 0
		tree = {0}
		pq = []
		for (c, v) in edges[0]:
			pq.append([c, v])
		heapify(pq)
		while len(tree) < len(points):
			(c, v) = heappop(pq)
			if v in tree:
				continue
			tree.add(v)
			cost += c
			for (d, u) in edges[v]:
				if not u in tree:
					heappush(pq, [d, u])
		return cost


class DisjoinSet:

	def __init__(self, n):
		self.parent = [i for i in range(n)]

	def find(self, x):
		if self.parent[x] != x:
			self.parent[x] = self.find(self.parent[x])
		return self.parent[x]

	def union(self, x, y):
		xr = self.find(x)
		yr = self.find(y)
		if xr != yr:
			self.parent[yr] = xr
			return True
		return False

class Solution:

	def minCostConnectPoints(self, points):
		n = len(points)
		graph = []
		ds = DisjoinSet(n)
		for i in range(n):
			for j in range(i + 1, n):
				dist = self.getDist(points[i], points[j])
				graph.append((dist, i, j))
		graph.sort()
		res = 0
		for (dist, u, v) in graph:
			if ds.union(u, v):
				res += dist
		return res

	def getDist(self, x, y):
		return abs(x[0] - y[0]) + abs(x[1] - y[1])


class DSU:

	def __init__(self, size):
		self.indexes = {i: i for i in range(size)}

	def root(self, i):
		node = i
		while i != self.indexes[i]:
			i = self.indexes[i]
		while node != i:
			nnode = self.indexes[node]
			self.indexes[node] = i
			node = nnode
		return i

	def unite(self, i, j):
		(ri, rj) = (self.root(i), self.root(j))
		if ri == rj:
			return
		self.indexes[rj] = ri

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				(x, y) = (points[i][0], points[i][1])
				(u, v) = (points[j][0], points[j][1])
				edges.append((abs(u - x) + abs(v - y), i, j))
		edges.sort()
		dsu = DSU(len(points))
		ans = 0
		for (dis, u, v) in edges:
			if dsu.root(u) == dsu.root(v):
				continue
			dsu.unite(u, v)
			ans += dis
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) <= 1:
			return 0

		def dist(a, b):
			return abs(a[1] - b[1]) + abs(a[0] - b[0])
		A = {i: {i} for i in range(len(points))}
		edges = [(dist(p1, p2), i, j) for (i, p1) in enumerate(points) for (j, p2) in enumerate(points) if p1 != p2]
		import heapq
		heapq.heapify(edges)
		tot = 0
		n = len(points) - 1
		while n:
			(w, a, b) = heapq.heappop(edges)
			if not A[a].intersection(A[b]):
				B = A[a].union(A[b])
				for b in B:
					A[b] = B
				tot += w
				n -= 1
		print((A[0], len(points)))
		return tot


from heapq import heappush, heappop

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def calcCost(i, j):
			return abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
		(totalCost, visited, q) = (0, set(), [(0, 0)])
		while len(visited) != len(points):
			(cost, point) = heappop(q)
			if point not in visited:
				visited.add(point)
				totalCost += cost
				for i in range(len(points)):
					if i != point:
						heappush(q, (calcCost(point, i), i))
		return totalCost


from heapq import *

class Solution:

	def minCostConnectPoints(self, points):
		N = len(points)
		dist = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		edges = [[] * N for _ in range(N)]
		for (i1, p1) in enumerate(points):
			for (i2, p2) in enumerate(points[i1 + 1:], start=i1 + 1):
				distance = dist(p1, p2)
				edges[i1].append([distance, i2])
				edges[i2].append([distance, i1])
		heap = edges[0]
		heapify(heap)
		(total_cost, seen) = (0, {0})
		while len(seen) < N:
			(cost, node) = heappop(heap)
			if node in seen:
				continue
			seen.add(node)
			total_cost += cost
			for (dist, next_) in edges[node]:
				if next_ not in seen:
					heappush(heap, [dist, next_])
		return total_cost


class Solution:

	def minCostConnectPoints(self, A: List[List[int]], total=0) -> int:
		N = len(A)
		cand = set([i for i in range(1, N)])
		E = [[float('inf')] * N for _ in range(N)]
		for u in range(N):
			(x1, y1) = A[u]
			for v in range(u + 1, N):
				(x2, y2) = A[v]
				cost = abs(x1 - x2) + abs(y1 - y2)
				E[u][v] = cost
				E[v][u] = cost
		s = 0
		q = []
		best = [float('inf')] * N
		for v in range(1, N):
			if best[v] > E[s][v]:
				best[v] = E[s][v]
				heappush(q, [best[v], v])
		while len(cand):
			(cost, u) = heappop(q)
			if u not in cand:
				continue
			cand.remove(u)
			total += cost
			for v in range(N):
				if v not in cand:
					continue
				if best[v] > E[u][v]:
					best[v] = E[u][v]
					heappush(q, [best[v], v])
		return total


from heapq import heapify, heappush, heappop
from collections import defaultdict

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def distance(point1, point2):
			(x1, y1) = point1
			(x2, y2) = point2
			return abs(x1 - x2) + abs(y1 - y2)
		n = len(points)
		if n == 1:
			return 0
		points = [tuple(p) for p in points]
		cost = defaultdict(list)
		for i in range(n):
			point1 = points[i]
			for j in range(i + 1, n):
				point2 = points[j]
				d = distance(point1, point2)
				cost[point1].append((d, point2))
				cost[point2].append((d, point1))
		ans = 0
		visited = {points[0]}
		heap = cost[points[0]]
		heapify(heap)
		while len(visited) != n:
			(d, v) = heappop(heap)
			if v not in visited:
				visited.add(v)
				ans += d
				for record in cost[v]:
					heappush(heap, record)
		return ans


from heapq import heappush, heappop

class Solution:

	def manhattan(self, point1, point2):
		return abs(point1[0] - point2[0]) + abs(point1[1] - point2[1])

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		graph = defaultdict(list)
		n = len(points)
		for i in range(n):
			for j in range(n):
				if i != j:
					graph[i].append([self.manhattan(points[i], points[j]), j])
		heap = [(0, 0)]
		visited = set()
		answer = 0
		while len(visited) < n:
			(distance, node) = heappop(heap)
			if node in visited:
				continue
			visited.add(node)
			answer += distance
			for (weight, nei) in graph[node]:
				if nei not in visited:
					heappush(heap, (weight, nei))
		return answer


class DisjointSet:

	def __init__(self, size):
		self.size = size
		self.parents = list(range(size))

	def find(self, node):
		if node != self.parents[node]:
			self.parents[node] = self.find(self.parents[node])
		return self.parents[node]

	def union(self, node1, node2):
		parent1 = self.find(node1)
		parent2 = self.find(node2)
		if parent1 != parent2:
			self.parents[parent1] = parent2
			return True
		return False

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		N = len(points)
		is_connected = [False] * N
		edges = []
		for i in range(N):
			for j in range(i + 1, N):
				distance = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				edges.append((distance, i, j))
		edges.sort()
		cost = 0
		disjoint_set = DisjointSet(N)
		for (distance, i, j) in edges:
			if disjoint_set.union(i, j):
				cost += distance
		return cost


class UnionFind:

	def __init__(self, n):
		self.parents = [i for i in range(n)]

	def union(self, index1, index2):
		root1 = self.find(index1)
		root2 = self.find(index2)
		if root1 == root2:
			return 0
		elif root1 > root2:
			self.parents[root2] = root1
		else:
			self.parents[root1] = root2
		return 1

	def find(self, index):
		if self.parents[index] != index:
			self.parents[index] = self.find(self.parents[index])
		return self.parents[index]

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) <= 1:
			return 0
		edges = []
		for (i, point1) in enumerate(points):
			for j in range(i + 1, len(points)):
				point2 = points[j]
				distance = abs(point1[0] - point2[0]) + abs(point1[1] - point2[1])
				edges.append((distance, i, j))
		edges.sort()
		uf = UnionFind(len(points))
		total = 0
		for (i, (weight, node1, node2)) in enumerate(edges):
			is_union = uf.union(node1, node2)
			if is_union:
				total += weight
		return total


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		cache = []
		l = len(points)
		if l == 1:
			return 0
		for i in range(l - 1):
			for j in range(i + 1, l):
				start = points[i]
				end = points[j]
				length = abs(start[0] - end[0]) + abs(start[1] - end[1])
				cache.append([length, i, j])
		cache.sort()
		res = 0
		t = len(cache)
		count = 0
		group = []
		for i in range(t):
			curr = cache[i]
			g = len(group)
			a = None
			b = None
			for j in range(g):
				if curr[1] in group[j]:
					a = j
				if curr[2] in group[j]:
					b = j
			if a == None and b == None:
				group.append({curr[1], curr[2]})
			elif a == None:
				group[b].add(curr[1])
			elif b == None:
				group[a].add(curr[2])
			elif a == b:
				continue
			else:
				group[a] = group[a] | group[b]
				group.pop(b)
			count += 1
			res += curr[0]
			if count == l - 1:
				return res


from heapq import *

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if not points:
			return 0
		adjList = self.buildAdjList(points)
		heap = [(0, 0, 0)]
		visited = set()
		minCost = 0
		while heap and len(visited) != len(adjList):
			(cost, i, j) = heappop(heap)
			if j in visited:
				continue
			visited.add(j)
			minCost += cost
			for (nj, cost) in adjList[j]:
				if nj not in visited:
					heappush(heap, (cost, j, nj))
		return minCost

	def buildAdjList(self, points):
		adjList = {}
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				(x1, y1) = points[i]
				(x2, y2) = points[j]
				if i not in adjList:
					adjList[i] = []
				if j not in adjList:
					adjList[j] = []
				weight = abs(x1 - x2) + abs(y1 - y2)
				adjList[i].append((j, weight))
				adjList[j].append((i, weight))
		return adjList


import math

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				edges.append((abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j))
		edges.sort()
		union_find = UnionFind(len(points))
		min_sum = 0
		for (d, i, j) in edges:
			if union_find.union(i, j):
				min_sum += d
		return min_sum

class UnionFind:

	def __init__(self, n):
		self.parent = [i for i in range(n)]
		self.size = [1 for i in range(n)]

	def find(self, p):
		root = p
		while root != self.parent[root]:
			root = self.parent[root]
		node = p
		while node != self.parent[node]:
			nextNode = self.parent[node]
			self.parent[node] = root
			node = nextNode
		return root

	def union(self, p, q):
		p_root = self.find(p)
		q_root = self.find(q)
		if p_root == q_root:
			return False
		if self.size[p_root] < self.size[q_root]:
			self.parent[p_root] = q_root
			self.size[q_root] += self.size[p_root]
		else:
			self.parent[q_root] = p_root
			self.size[p_root] += self.size[q_root]
		return True


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		graph = defaultdict(list)
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				cost = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				graph[i].append((cost, j))
				graph[j].append((cost, i))
		seen = [0] * (len(points) + 1)
		seen[0] = 1
		q = graph[0]
		minimumCost = 0
		connectedNodes = 1
		heapq.heapify(q)
		while q:
			(cost, point) = heapq.heappop(q)
			if not seen[point]:
				seen[point] = 1
				minimumCost += cost
				connectedNodes += 1
				for (connectingCost, neighbour) in graph[point]:
					heapq.heappush(q, (connectingCost, neighbour))
			if connectedNodes >= len(points):
				break
		return minimumCost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) < 2:
			return 0
		e = [[] for _ in points]
		n = len(points)
		for (i, u) in enumerate(points):
			for j in range(i + 1, n):
				v = points[j]
				d = abs(u[0] - v[0]) + abs(u[1] - v[1])
				e[i].append((d, j))
				e[j].append((d, i))
		tree = {0}
		pq = []
		for v in e[0]:
			pq.append(v)
		heapify(pq)
		c = 0
		while len(tree) < n:
			try:
				(d, v) = heappop(pq)
			except IndexError:
				break
			if v in tree:
				continue
			c += d
			tree.add(v)
			for u in e[v]:
				heappush(pq, u)
		return c


class Union_Find:

	def __init__(self, n):
		self.father = {i: i for i in range(n)}
		self.count = n
		self.rank = [1] * n

	def find(self, x):
		if self.father[x] == x:
			return x
		self.father[x] = self.find(self.father[x])
		return self.father[x]

	def union(self, x, y):
		if self.rank[x] < self.rank[y]:
			(x, y) = (y, x)
		self.father[y] = x
		self.rank[x] += self.rank[y]
		self.count -= 1

	def find_union(self, x, y):
		(father_x, father_y) = (self.find(x), self.find(y))
		if father_x != father_y:
			self.union(father_x, father_y)
			return True
		return False

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		mst = collections.defaultdict(set)
		n = len(points)
		graph = []
		uf = Union_Find(n)
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				cost = cost = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				graph.append([i, j, cost])
		result = 0
		for (a, b, c) in sorted(graph, key=lambda x: x[2]):
			if uf.find_union(a, b):
				result += c
		return result


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		from queue import PriorityQueue
		q = PriorityQueue()
		l = len(points)
		visited = set()
		for j in range(1, l):
			q.put((abs(points[0][0] - points[j][0]) + abs(points[0][1] - points[j][1]), j))
		visited.add(0)
		count = 1
		ans = 0
		while count < l:
			(dis, point) = q.get()
			if point not in visited:
				visited.add(point)
				for j in range(l):
					if j not in visited:
						q.put((abs(points[point][0] - points[j][0]) + abs(points[point][1] - points[j][1]), j))
				ans += dis
				count += 1
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def union(g, u, v):
			p = g[u]
			o = g[v]
			for i in g.keys():
				if g[i] == o:
					g[i] = p
		N = len(points)
		matrix = [[float('inf')] * N for _ in range(N)]
		ans = 0
		edges = []
		for node in range(N):
			for neighbor in range(N):
				if node == neighbor:
					continue
				if matrix[node][neighbor] != float('inf'):
					continue
				(u, v) = (points[node], points[neighbor])
				d = abs(u[0] - v[0]) + abs(u[1] - v[1])
				matrix[node][neighbor] = d
				matrix[neighbor][node] = d
				edges.append((node, neighbor, d))
				edges.append((neighbor, node, d))
		P = {_: _ for _ in range(N)}
		edges.sort(key=lambda x: x[2])
		for (u, v, w) in edges:
			if P[u] != P[v]:
				union(P, u, v)
				ans += w
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		length = len(points)
		if length < 2:
			return 0
		dist = [[0] * len(points) for _ in range(len(points))]
		value = float('inf')
		for i in range(length):
			dist[i][i] = float('inf')
			for j in range(length):
				if i != j:
					dist[i][j] = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				if dist[i][j] < value:
					value = dist[i][j]
					(idx_i, idx_j) = (i, j)
		(connected, result) = (set([idx_i, idx_j]), dist[idx_i][idx_j])
		heap_q = []

		def increaseQ(heap_q: List[int], idx: int, connected: Set[int]):
			for j in range(length):
				if j not in connected:
					heapq.heappush(heap_q, (dist[idx][j], idx, j))
		increaseQ(heap_q, idx_i, connected)
		increaseQ(heap_q, idx_j, connected)
		while len(connected) < length:
			(v, idx_i, idx_j) = heapq.heappop(heap_q)
			if idx_i not in connected:
				connected.add(idx_i)
				increaseQ(heap_q, idx_i, connected)
				result += v
			if idx_j not in connected:
				connected.add(idx_j)
				increaseQ(heap_q, idx_j, connected)
				result += v
		return result


class Solution:

	def minCostConnectPoints(self, points):
		helper = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		points.sort(key=lambda p: p[0] + p[1])
		points = [[p, helper(p, points[0])] for p in points]
		total_cost = 0
		while points:
			(minI, minD) = (None, float('inf'))
			for (i, (p, d)) in enumerate(points):
				if d < minD:
					(minI, minD) = (i, d)
			(p1, cost) = points.pop(minI)
			total_cost += cost
			for (i, (p2, _)) in enumerate(points):
				points[i][1] = min(points[i][1], helper(p1, p2))
		return total_cost


class DSU:

	def __init__(self, n):
		self.par = [i for i in range(n)]

	def find(self, x):
		if self.par[x] == x:
			return x
		self.par[x] = self.find(self.par[x])
		return self.par[x]

	def union(self, x, y):
		(px, py) = (self.find(x), self.find(y))
		if px == py:
			return
		self.par[px] = py
		return

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def dist(x, y):
			return abs(x[0] - y[0]) + abs(x[1] - y[1])
		cnt = 0
		n = len(points)
		needs = n - 1
		dsu = DSU(n)
		dists = [(dist(points[i], points[j]), i, j) for i in range(n) for j in range(n) if i != j]
		dists.sort()
		i = 0
		while i < len(dists) and needs:
			(d, x, y) = dists[i]
			(px, py) = (dsu.find(x), dsu.find(y))
			if px == py:
				i += 1
			else:
				cnt += d
				dsu.union(x, y)
				needs -= 1
		return cnt


from heapq import heappush, heappop

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		points.sort()
		visited = set()
		n = len(points)
		cnt = 0
		q = []
		heappush(q, (0, 0))
		while len(q):
			(weight, source) = heappop(q)
			if source in visited:
				continue
			cnt += weight
			visited.add(source)
			for i in range(n):
				if i not in visited:
					weight = abs(points[i][0] - points[source][0]) + abs(points[i][1] - points[source][1])
					heappush(q, (weight, i))
		return cnt


class Solution:

	def minCostConnectPoints(self, a: List[List[int]]) -> int:
		n = len(a)
		if n <= 1:
			return 0
		(d, cur, min_d) = (dict(), set(), float('inf'))
		for i in range(n - 1):
			for j in range(n):
				d[i, j] = d[j, i] = abs(a[i][0] - a[j][0]) + abs(a[i][1] - a[j][1])
				if min_d > d[i, j]:
					min_d = d[i, j]
					cur = set([i, j])
		(rem, cand) = (set(range(n)) - cur, [])
		for x in cur:
			for y in rem:
				cand.append((d[x, y], x, y))
		heapify(cand)
		ans = min_d
		while len(cur) < n:
			(val, x, y) = heappop(cand)
			if y not in cur:
				cur.add(y)
				rem.discard(y)
				ans += val
				for z in rem:
					heappush(cand, (d[y, z], y, z))
		return ans


class UnionFind:

	def __init__(self, n):
		self.count = n
		self.id = list(range(n))

	def connected(self, p, q):
		return self.find(p) == self.find(q)

	def find(self, p):
		if p == self.id[p]:
			return p
		return self.find(self.id[p])

	def union(self, p, q):
		idp = self.find(p)
		idq = self.find(q)
		if not self.connected(p, q):
			self.id[idp] = idq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		distance = lambda i, j: abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
		graph = collections.defaultdict(list)
		hp = []
		n = len(points)
		for i in range(n):
			for j in range(n):
				if i != j:
					graph[i].append((distance(i, j), j))
		(start, cost) = (0, 0)
		visited = {0}
		for to in graph[0]:
			heapq.heappush(hp, to)
		while len(visited) != n and len(hp):
			(dist, to) = heapq.heappop(hp)
			if to not in visited:
				visited.add(to)
				cost += dist
				for t in graph[to]:
					heapq.heappush(hp, t)
		return cost


class DSU:

	def __init__(self, n):
		self.p = list(range(n))

	def find(self, x):
		if self.p[x] != x:
			self.p[x] = self.find(self.p[x])
		return self.p[x]

	def union(self, x, y):
		r1 = self.find(x)
		r2 = self.find(y)
		if r1 != r2:
			self.p[r1] = r2
			return True
		return False

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		dsu = DSU(len(points))

		def getDistance(point1, point2):
			(x1, y1) = point1
			(x2, y2) = point2
			return abs(x1 - x2) + abs(y1 - y2)
		paths = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				dis = getDistance(points[i], points[j])
				paths.append((dis, i, j))
		paths.sort()
		cost = 0
		for (dis, i, j) in paths:
			if dsu.union(i, j):
				cost += dis
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		if n == 1:
			return 0
		mapper = collections.defaultdict(dict)
		for (ind1, point1) in enumerate(points):
			for (ind2, point2) in enumerate(points):
				dis = abs(point1[0] - point2[0]) + abs(point1[1] - point2[1])
				mapper[ind1][ind2] = dis
				mapper[ind2][ind1] = dis
		cost = 0
		c = set()
		unc = set(range(n))
		(min_i, min_j) = (None, None)
		min_d = math.inf
		for i in range(n):
			for j in range(n):
				if i != j and mapper[i][j] < min_d:
					(min_i, min_j) = (i, j)
					min_d = mapper[i][j]
		cost += min_d
		c.add(min_i)
		c.add(min_j)
		unc.remove(min_i)
		unc.remove(min_j)
		mins = dict()
		for i in unc:
			mins[i] = min(mapper[i][min_i], mapper[i][min_j])
		while unc:
			min_i = None
			min_d = math.inf
			for i in unc:
				if mins[i] < min_d:
					min_i = i
					min_d = mins[i]
			cost += min_d
			c.add(min_i)
			unc.remove(min_i)
			for i in unc:
				mins[i] = min(mins[i], mapper[i][min_i])
		return cost


import bisect

class Union:

	def __init__(self, n):
		self.parents = [-1 for _ in range(n)]
		self.ranks = [0 for _ in range(n)]
		self.n = n

	def join(self, i, j):
		i = self.find(i)
		j = self.find(j)
		if self.ranks[i] > self.ranks[j]:
			self.parents[j] = i
		elif self.ranks[j] > self.ranks[i]:
			self.parents[i] = j
		else:
			self.parents[j] = i
			self.ranks[i] += 1

	def find(self, i):
		i_ori = i
		while self.parents[i] != -1:
			i = self.parents[i]
		if i != i_ori:
			self.parents[i_ori] = i
		return i
from collections import defaultdict

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def calc_distance(p1, p2):
			(x1, y1) = p1
			(x2, y2) = p2
			return abs(x1 - x2) + abs(y1 - y2)

		def find_best_node(min_dists, mst_set):
			min_dist = float('inf')
			for (i, dist) in enumerate(min_dists):
				if i not in mst_set and dist < min_dist:
					best_node = i
					min_dist = dist
			return (best_node, min_dist)

		def update_min_dists(node, min_dists, graph):
			for (i, dist) in graph[node]:
				min_dists[i] = min(min_dists[i], dist)
		n = len(points)
		if n <= 1:
			return 0
		graph = defaultdict(list)
		for i in range(n):
			for j in range(i + 1, n):
				(p1, p2) = (points[i], points[j])
				dist = calc_distance(p1, p2)
				graph[i].append((j, dist))
				graph[j].append((i, dist))
		min_dists = [float('inf') for _ in range(n)]
		mst_set = {0}
		for (i, dist) in graph[0]:
			min_dists[i] = min(min_dists[i], dist)
		total_dist = 0
		for _ in range(n - 1):
			(best_node, min_dist) = find_best_node(min_dists, mst_set)
			mst_set.add(best_node)
			update_min_dists(best_node, min_dists, graph)
			total_dist += min_dist
		return total_dist


class Union:

	def __init__(self, n):
		self.components = n
		self.parent = [i for i in range(n)]

	def find(self, i):
		if i != self.parent[i]:
			self.parent[i] = self.find(self.parent[i])
		return self.parent[i]

	def _union(self, i, j):
		x = self.find(i)
		y = self.find(j)
		if x != y:
			self.parent[x] = y
			self.components -= 1
			return True
		return False

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		graph = []
		for i in range(n):
			for j in range(i + 1, n):
				d = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				graph.append([i, j, d])
		graph = sorted(graph, key=lambda x: x[2])
		k = len(graph)
		if k == 0:
			return 0
		elif k == 1:
			return graph[0][2]
		x = Union(k)
		result = 0
		for i in range(k):
			if x._union(graph[i][0], graph[i][1]):
				result += graph[i][2]
			if x.components == 1:
				return result
		return result


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		N = len(points)
		seen = set()
		cost = 0
		cnt = 0
		pq = [(0, 0)]
		while pq:
			(c, i) = heapq.heappop(pq)
			if i in seen:
				continue
			cost += c
			cnt += 1
			if cnt == N:
				return cost
			seen.add(i)
			(pt_x, pt_y) = points[i]
			for j in range(N):
				if j in seen:
					continue
				(nei_x, nei_y) = points[j]
				nei_c = abs(pt_x - nei_x) + abs(pt_y - nei_y)
				heapq.heappush(pq, (nei_c, j))
		return cost


import sys
input = sys.stdin.readline

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		import math as mt
		re = lambda x, y: abs(x[0] - y[0]) + abs(x[1] - y[1])
		ar = []
		n = len(points)
		par = [i for i in range(len(points) + 1)]

		def find(i):
			while i != par[i]:
				i = par[i]
			return par[i]

		def join(i, j):
			a = find(i)
			b = find(j)
			if a != b:
				par[a] = par[b] = min(a, b)
		for i in range(n):
			for j in range(i + 1, n):
				temp = re(points[i], points[j])
				ar.append([temp, i, j])
		ans = 0
		cnt = 0
		ar.sort()
		for (a, b, c) in ar:
			if find(b) != find(c):
				join(b, c)
				ans += a
				cnt += 1
			if cnt == n - 1:
				break
		return ans


from typing import List
from heapq import heappop, heappush

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		visited = [False] * len(points)
		cost = 0
		pq = [(0, 0)]
		get_dist = lambda i, j: abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
		while pq:
			(dist, node) = heappop(pq)
			if visited[node]:
				continue
			else:
				visited[node] = True
			cost += dist
			for adj in range(len(points)):
				if not visited[adj]:
					heappush(pq, (get_dist(node, adj), adj))
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		cache = {}
		for (i, coord) in enumerate(points):
			cache[i] = coord

		def compute(p1, p2):
			(x1, y1) = cache[p1]
			(x2, y2) = cache[p2]
			return abs(x1 - x2) + abs(y1 - y2)
		edges = []
		for (x, y) in combinations(list(cache.items()), 2):
			edges.append((compute(x[0], y[0]), x[0], y[0]))
		edges.sort(reverse=True)
		ans = 0
		L = len(cache)
		parents = list(range(L))

		def union(x, y):
			parents[find(x)] = find(y)

		def find(x):
			if parents[x] != x:
				parents[x] = find(parents[x])
			return parents[x]
		if L == 1:
			return 0
		while edges:
			(cost, n1, n2) = edges.pop()
			if find(n1) != find(n2):
				union(n1, n2)
				ans += cost
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		uf = UF(len(points))
		n = len(points)
		for (i, ps) in enumerate(points):
			j = i + 1
			while j < n:
				pt = points[j]
				dist = abs(ps[0] - pt[0]) + abs(ps[1] - pt[1])
				uf.addEdge(i, j, dist)
				j += 1
		return uf.exec()

class UF:

	def __init__(self, n):
		self.n = n
		self.g = []

	def addEdge(self, s, t, cost):
		self.g.append((s, t, cost))

	def find(self, x, parent):
		if parent[x] == x:
			return x
		return self.find(parent[x], parent)

	def union(self, x, y, parent, rank):
		(xroot, yroot) = (self.find(x, parent), self.find(y, parent))
		if xroot != yroot:
			if rank[xroot] > rank[yroot]:
				parent[yroot] = xroot
				return xroot
			elif rank[xroot] < rank[yroot]:
				parent[xroot] = yroot
				return yroot
			else:
				parent[yroot] = xroot
				rank[xroot] += 1
				return xroot
		else:
			return xroot

	def exec(self):
		parent = [_ for _ in range(self.n)]
		rank = [0] * self.n
		self.g.sort(key=lambda edge: edge[2])
		totalans = 0
		for edge in self.g:
			x = edge[0]
			y = edge[1]
			xroot = self.find(x, parent)
			yroot = self.find(y, parent)
			if xroot != yroot:
				self.union(x, y, parent, rank)
				totalans += edge[2]
		return totalans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		costs = []
		for i in range(len(points)):
			(xi, yi) = points[i]
			for j in range(i + 1, len(points)):
				(xj, yj) = points[j]
				costs.append([abs(xi - xj) + abs(yi - yj), i, j])
		costs = sorted(costs)
		fathers = [t for t in range(len(points))]

		def get_father(n):
			while not fathers[n] == fathers[fathers[n]]:
				fathers[n] = fathers[fathers[n]]
			return fathers[n]
		res = 0
		for t in costs:
			(dist, i, j) = t
			if get_father(i) == get_father(j):
				continue
			fathers[get_father(j)] = get_father(i)
			res += dist
		return res


class UnionFind:

	def __init__(self, size):
		self.size = size
		self.components = size
		self.parent = [0] * size
		self.sizeArray = [0] * size
		for i in range(size):
			self.parent[i] = i
			self.sizeArray[i] = 1

	def find(self, a):
		while a != self.parent[a]:
			a = self.parent[a]
		return a

	def unify(self, a, b):
		p_a = self.find(a)
		p_b = self.find(b)
		if p_a == p_b:
			return
		if self.sizeArray[p_a] < self.sizeArray[p_b]:
			self.sizeArray[p_b] += self.sizeArray[p_a]
			self.parent[p_a] = p_b
		else:
			self.sizeArray[p_a] += self.sizeArray[p_b]
			self.parent[p_b] = p_a
		self.components -= 1

	def num_components(self):
		return self.components

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []
		n = len(points)
		_map = {}
		k = 0
		for p in points:
			_map[p[0], p[1]] = k
			k += 1
		for i in range(n):
			for j in range(i + 1, n):
				u = points[i]
				v = points[j]
				dist = abs(u[0] - v[0]) + abs(u[1] - v[1])
				edges.append((u, v, dist))
		edges.sort(key=lambda x: x[2])
		ds = UnionFind(n)
		min_cost = 0
		for edge in edges:
			u = _map[edge[0][0], edge[0][1]]
			v = _map[edge[1][0], edge[1][1]]
			d = edge[2]
			if ds.find(u) != ds.find(v):
				ds.unify(u, v)
				min_cost += d
		return min_cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		cost = []
		for i in range(n):
			for j in range(i + 1, n):
				if i != j:
					(x1, y1) = points[i]
					(x2, y2) = points[j]
					cost.append([abs(x1 - x2) + abs(y1 - y2), i, j])
		cost.sort()
		parent = [i for i in range(n)]
		rank = [1 for _ in range(n)]

		def find(parent, i):
			if parent[i] == i:
				return i
			return find(parent, parent[i])

		def union(parent, rank, x, y):
			xroot = find(parent, x)
			yroot = find(parent, y)
			if rank[xroot] < rank[yroot]:
				parent[xroot] = yroot
			elif rank[xroot] > rank[yroot]:
				parent[yroot] = xroot
			else:
				parent[yroot] = xroot
				rank[xroot] += 1
		(i, e) = (0, 0)
		ans = 0
		while e < n - 1:
			(w, u, v) = cost[i]
			i += 1
			x = find(parent, u)
			y = find(parent, v)
			if x != y:
				e = e + 1
				ans += w
				union(parent, rank, x, y)
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				d = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				edges.append((d, i, j))
		edges.sort()
		parent = {i: i for i in range(len(points))}

		def find(x):
			if not parent[x] == x:
				parent[x] = find(parent[x])
			return parent[x]

		def union(x, y):
			par_x = find(x)
			par_y = find(y)
			if not par_x == par_y:
				parent[par_x] = parent[par_y]
				return True
			return False
		res = 0
		for (d, u, v) in edges:
			if union(u, v):
				res += d
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		import heapq
		stack = []
		ans = 0
		used = set([0])
		ps = set([0])
		while ps:
			i = ps.pop()
			for j in range(len(points)):
				if i != j and j not in used:
					dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
					heappush(stack, (dist, i, j))
			while stack:
				(dist, x, y) = heappop(stack)
				if x in used and y not in used:
					ans += dist
					used.add(y)
					ps.add(y)
					break
				elif y in used and x not in used:
					ans += dist
					used.add(x)
					ps.add(x)
					break
		return ans


import heapq

class Solution:

	def minCostConnectPoints(self, P: List[List[int]]) -> int:
		p = P[0]
		q = []
		for (x, y) in P[1:]:
			d = abs(x - p[0]) + abs(y - p[1])
			heapq.heappush(q, (d, x, y))
		seen = {(p[0], p[1])}
		res = 0
		while q:
			(d, x, y) = heapq.heappop(q)
			if (x, y) in seen:
				continue
			res += d
			seen.add((x, y))
			for (x1, y1) in P:
				if (x1, y1) not in seen:
					d = abs(x1 - x) + abs(y1 - y)
					heapq.heappush(q, (d, x1, y1))
		return res


class UnionFind:

	def __init__(self, n):
		self.sets = {i: i for i in range(n)}
		self.n_sets = n

	def find(self, s):
		if self.sets[s] != s:
			self.sets[s] = self.find(self.sets[s])
		return self.sets[s]

	def union(self, s1, s2):
		(a, b) = (self.find(s1), self.find(s2))
		if a == b:
			return False
		self.sets[a] = b
		self.n_sets -= 1
		return True

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []
		N = len(points)
		for i in range(N):
			for j in range(i + 1, N):
				(p1, p2) = (points[i], points[j])
				edges.append((abs(p1[0] - p2[0]) + abs(p1[1] - p2[1]), i, j))
		edges.sort()
		uf = UnionFind(N)
		res = 0
		for (w, u, v) in edges:
			if uf.union(u, v):
				res += w
		return res


class DJSet:

	def __init__(self, n):
		self.par = [i for i in range(n)]
		self.size = [1 for i in range(n)]

	def find(self, x):
		if self.par[x] != x:
			self.par[x] = self.find(self.par[x])
		return self.par[x]

	def union(self, x, y):
		(px, py) = (self.find(x), self.find(y))
		if px == py:
			return False
		if self.size[px] < self.size[py]:
			(px, py) = (py, px)
		self.par[py] = px
		self.size[px] += self.size[py]
		return True

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		a = []
		for i in range(n):
			for j in range(i + 1, n):
				a.append((abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j))
		a.sort()
		ans = 0
		djSet = DJSet(n)
		for (v, i, j) in a:
			if djSet.union(i, j):
				ans += v
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) <= 1:
			return 0
		res = 0
		seen = set()
		seen.add((points[0][0], points[0][1]))
		minD = []
		for i in range(len(points)):
			if (points[i][0], points[i][1]) not in seen:
				heapq.heappush(minD, (abs(points[i][0] - points[0][0]) + abs(points[i][1] - points[0][1]), [points[i][0], points[i][1]]))
		while len(seen) < len(points):
			while minD:
				curMinD = heapq.heappop(minD)
				if (curMinD[1][0], curMinD[1][1]) not in seen:
					break
			res += curMinD[0]
			seen.add((curMinD[1][0], curMinD[1][1]))
			for i in range(len(points)):
				if (points[i][0], points[i][1]) not in seen:
					heapq.heappush(minD, (abs(points[i][0] - curMinD[1][0]) + abs(points[i][1] - curMinD[1][1]), [points[i][0], points[i][1]]))
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		N = len(points)
		edges = []
		parent = [x for x in range(N)]

		def ufind(x):
			if parent[x] != x:
				parent[x] = ufind(parent[x])
			return parent[x]

		def uunion(x, y):
			ux = ufind(x)
			uy = ufind(y)
			parent[ux] = uy

		def dist(a, b):
			return abs(points[a][0] - points[b][0]) + abs(points[a][1] - points[b][1])
		for i in range(N):
			for j in range(i + 1, N):
				edges.append((dist(i, j), i, j))
		edges.sort()
		total = 0
		for (cost, x, y) in edges:
			if ufind(x) != ufind(y):
				uunion(x, y)
				total += cost
		return total


import math

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		edges = set()
		for i in range(n):
			p = points[i]
			for j in range(n):
				if i != j:
					w = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
					e = (min(i, j), max(i, j), w)
					edges.add(e)
		edges = sorted(edges, key=lambda x: x[2])
		tree_id = [0] * n
		for i in range(n):
			tree_id[i] = i
		cost = 0
		for i in edges:
			v1 = i[0]
			v2 = i[1]
			w = i[2]
			if tree_id[v1] != tree_id[v2]:
				cost += w
				old_tree = tree_id[v1]
				new_tree = tree_id[v2]
				for j in range(n):
					if tree_id[j] == old_tree:
						tree_id[j] = new_tree
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		edges = []
		for i in range(n - 1):
			for j in range(i + 1, n):
				(u, v) = points[i]
				(p, q) = points[j]
				w = abs(u - p) + abs(v - q)
				edges.append([w, i, j])
		path = [u for u in range(n)]

		def find(u: int) -> int:
			if path[u] != u:
				path[u] = find(path[u])
			return path[u]

		def union(u: int, v: int) -> bool:
			(i, j) = (find(u), find(v))
			if i == j:
				return False
			if j > i:
				(i, j) = (j, i)
			path[j] = i
			return True
		costs = 0
		edges.sort()
		for (w, u, v) in edges:
			if find(u) != find(v):
				costs += w
				union(u, v)
		return costs


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		mst = set()
		mst.add(0)
		md = 0
		pq = []
		for i in range(n):
			if i not in mst:
				distance = abs(points[0][0] - points[i][0]) + abs(points[0][1] - points[i][1])
				heapq.heappush(pq, (distance, 0, i))
		while pq:
			(distance, a, b) = heapq.heappop(pq)
			if b not in mst:
				mst.add(b)
				md += distance
				for i in range(n):
					if i not in mst:
						distance = abs(points[b][0] - points[i][0]) + abs(points[b][1] - points[i][1])
						heapq.heappush(pq, (distance, b, i))
		return md


class DSU:

	def __init__(self, N):
		self.sz = [1] * N
		self.par = list(range(N))

	def find(self, v):
		if self.par[v] != v:
			self.par[v] = self.find(self.par[v])
		return self.par[v]

	def union(self, u, v):
		px = self.find(u)
		py = self.find(v)
		if px == py:
			return False
		if self.sz[px] < self.sz[py]:
			(px, py) = (py, px)
		self.par[py] = px
		self.sz[px] += self.sz[py]
		return True

	def size(self, x):
		return self.sz[self.find(x)]

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		N = len(points)
		edges = []
		dsu = DSU(N)
		for i in range(N):
			for j in range(i + 1, N):
				d = abs(points[i][0] - points[j][0])
				d += abs(points[i][1] - points[j][1])
				edges.append([i, j, d])
		edges.sort(key=lambda key: key[2])
		ans = 0
		for (u, v, d) in edges:
			if dsu.union(u, v):
				ans += d
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		graph = []

		def getDistance(p1, p2):
			return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				graph.append((i, j, getDistance(points[i], points[j])))
		graph.sort(key=lambda x: x[2])
		rank = [1] * len(points)
		parent = list(range(len(points)))

		def getParent(parent, n):
			if parent[n] == n:
				return n
			value = getParent(parent, parent[n])
			parent[n] = value
			return value

		def union(parent, rank, n1, n2):
			if rank[n1] >= rank[n2]:
				parent[n2] = n1
				rank[n1] += rank[n2]
			else:
				parent[n1] = n2
				rank[n2] += rank[n1]
		min_cost = 0
		for edge in graph:
			(u, v, cost) = edge
			paru = getParent(parent, u)
			parv = getParent(parent, v)
			if parv != paru:
				min_cost += cost
				union(parent, rank, paru, parv)
		return min_cost


class UF:

	def __init__(self, n):
		self.parent = {i: i for i in range(n)}

	def find(self, a):
		if a != self.parent[a]:
			self.parent[a] = self.find(self.parent[a])
		return self.parent[a]

	def union(self, a, b):
		r_a = self.find(a)
		r_b = self.find(b)
		if r_a == r_b:
			return False
		self.parent[r_a] = r_b
		return True

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []
		n = len(points)
		for i in range(n):
			for j in range(i):
				dis = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				edges.append((dis, i, j))
		edges.sort()
		cost = 0
		uf = UF(n)
		for (dis, i, j) in edges:
			if uf.union(i, j):
				cost += dis
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def get_dist(p1, p2):
			(x1, y1) = p1
			(x2, y2) = p2
			return abs(x1 - x2) + abs(y1 - y2)
		N = len(points)
		res = 0
		minheap = [(0, 0)]
		seen = set()
		while minheap:
			(dist, p) = heapq.heappop(minheap)
			if p in seen:
				continue
			res += dist
			seen.add(p)
			for i in range(N):
				if i not in seen:
					heapq.heappush(minheap, (get_dist(points[p], points[i]), i))
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		uf = list(range(n))

		def find(x):
			if uf[x] != x:
				uf[x] = find(uf[x])
			return uf[x]

		def union(x, y):
			uf[find(x)] = find(y)
		costs = []
		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)
				costs.append([cost, i, j])
		costs.sort()
		res = 0
		for (cost, i, j) in costs:
			if find(i) != find(j):
				union(i, j)
				res += cost
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		diss = [[0] * n for _ in range(len(points))]
		res = 0
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				length = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				diss[i][j] = diss[j][i] = length
		disinfo = []
		for info in diss:
			tmp = []
			for (i, l) in enumerate(info):
				tmp.append((l, i))
			tmp.sort(reverse=True)
			disinfo.append(tmp)
		not_linked = set(range(1, len(points)))
		min_dis = diss[0].copy()
		min_dis[0] = math.inf
		while not_linked:
			nxt_dis = min(min_dis)
			res += nxt_dis
			nxt = min_dis.index(nxt_dis)
			not_linked.remove(nxt)
			min_dis[nxt] = math.inf
			for i in range(len(points)):
				if min_dis[i] < math.inf:
					min_dis[i] = min(diss[nxt][i], min_dis[i])
		return res


def distance(u, v):
	return abs(u[0] - v[0]) + abs(u[1] - v[1])

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		distances = []
		n = len(points)
		mini = 0
		parent = [i for i in range(n)]
		for i in range(n):
			for j in range(i + 1, n):
				(u, v) = (points[i], points[j])
				dis = distance(u, v)
				distances.append((dis, i, j))
		distances.sort()

		def find(i):
			while i != parent[i]:
				parent[i] = parent[parent[i]]
				i = parent[i]
			return i

		def union(i, j):
			(a, b) = (find(i), find(j))
			if a == b:
				return False
			else:
				parent[a] = b
				return True
		for (cost, i, j) in distances:
			if union(i, j):
				mini += cost
			else:
				mini += 0
		return mini


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def dist(e1, e2):
			return abs(e1[0] - e2[0]) + abs(e1[1] - e2[1])

		def find(x):
			while x in uf:
				while uf[x] in uf:
					uf[x] = uf[uf[x]]
				x = uf[x]
			return x

		def union(x, y):
			(px, py) = (find(x), find(y))
			if px == py:
				return False
			uf[px] = py
			return True
		n = len(points)
		res = 0
		uf = {}
		edges = []
		for i in range(n):
			for j in range(i + 1, n):
				edges.append([dist(points[i], points[j]), i, j])
		edges.sort()
		for (cost, x, y) in edges:
			if union(x, y):
				res += cost
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		if n == 1:
			return 0
		vis = set()
		points = list(map(tuple, points))
		q = [(0, points[0])]
		res = 0

		def get_dist(pointa, pointb):
			return abs(pointa[0] - pointb[0]) + abs(pointa[1] - pointb[1])
		while q:
			(top, curr_pt) = heappop(q)
			if curr_pt in vis:
				continue
			vis.add(curr_pt)
			res += top
			for point in set(points) - vis:
				heappush(q, (get_dist(curr_pt, point), point))
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		ln = len(points)
		if ln <= 1:
			return 0
		ans = 0
		par = {}

		def find(x):
			if x not in par:
				return x
			res = find(par[x])
			par[x] = res
			return res

		def union(a, b):
			n1 = find(a)
			n2 = find(b)
			if n1 != n2:
				if n1 < n2:
					par[n2] = n1
				else:
					par[n1] = n2
		arr = []
		for i in range(ln - 1):
			for j in range(i + 1, ln):
				n = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				arr.append((n, i, j))
		arr.sort()
		for x in arr:
			i = x[1]
			j = x[2]
			n1 = find(i)
			n2 = find(j)
			if n1 != n2:
				if n1 < n2:
					par[n2] = n1
				else:
					par[n1] = n2
				ans += x[0]
		return ans


class Solution:

	def _dist(self, a, b):
		return abs(a[0] - b[0]) + abs(a[1] - b[1])

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		result = 0
		comp = [points[0]]
		h = []
		for i in range(1, len(points)):
			heapq.heappush(h, [self._dist(points[0], points[i]), points[i]])
		while h:
			(dist, p) = heapq.heappop(h)
			result += dist
			for i in range(len(h)):
				h[i][0] = min(h[i][0], self._dist(p, h[i][1]))
			heapq.heapify(h)
		return result


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) <= 1:
			return 0

		def find(x):
			if x != parent[x]:
				parent[x] = find(parent[x])
				return parent[x]
			return x
		n = len(points)
		parent = list(range(n))
		dists = []
		for i in range(n - 1):
			for j in range(i + 1, n):
				mand = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				dists.append((mand, i, j))
		dists.sort(key=lambda item: item[0])
		res = 0
		for (w, a, b) in dists:
			pa = find(a)
			pb = find(b)
			if pa != pb:
				res += w
				parent[pa] = parent[pb]
		return res


class dsu:

	def __init__(self, n):
		self.ranks = [0] * n
		self.ids = list(range(n))
		pass

	def find(self, x):
		if x != self.ids[x]:
			self.ids[x] = self.find(self.ids[x])
			pass
		return self.ids[x]

	def union(self, x, y):
		rx = self.find(x)
		ry = self.find(y)
		if rx == ry:
			return False
		elif self.ranks[rx] == self.ranks[ry]:
			self.ids[ry] = rx
			self.ranks[rx] += 1
			pass
		elif self.ranks[rx] < self.ranks[ry]:
			self.ids[rx] = ry
			pass
		else:
			self.ids[ry] = rx
			pass
		return True

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		d = dsu(len(points))
		lst = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				t = (dist, i, j)
				lst.append(t)
				pass
			pass
		lst.sort()
		cost = 0
		for i in range(len(lst)):
			success = d.union(lst[i][1], lst[i][2])
			if success:
				cost += lst[i][0]
				pass
			pass
		return cost


class Union:

	def __init__(self, vertices):
		self.parent = [i for i in range(vertices)]

	def find(self, i):
		if self.parent[i] != i:
			return self.find(self.parent[i])
		return self.parent[i]

	def union(self, i, j):
		x = self.find(i)
		y = self.find(j)
		self.parent[x] = y

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		uf = Union(n)

		def dist(x, y):
			return abs(x[0] - y[0]) + abs(x[1] - y[1])
		costs = []
		for i in range(n):
			for j in range(n):
				costs.append([i, j, dist(points[i], points[j])])
		costs = sorted(costs, key=lambda x: x[2])
		ans = 0
		i = 0
		s = 0
		while s < n - 1:
			(u, v, cost) = costs[i]
			i += 1
			x = uf.find(u)
			y = uf.find(v)
			if x != y:
				uf.union(x, y)
				s += 1
				ans += cost
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def find(x):
			if x == parent[x]:
				return x
			return find(parent[x])

		def union(p, q):
			x = find(p)
			y = find(q)
			if rank[x] < rank[y]:
				parent[x] = y
			elif rank[y] < rank[x]:
				parent[y] = x
			else:
				parent[y] = x
				rank[x] += 1
		n = len(points)
		graph = []
		parent = {}
		rank = {}
		for i in range(n):
			for j in range(i + 1, n):
				w = abs(points[j][1] - points[i][1]) + abs(points[j][0] - points[i][0])
				graph.append([i, j, w])
		edges = sorted(graph, key=lambda k: k[2])
		for i in range(n):
			parent[i] = i
			rank[i] = 0
		ans = 0
		for (x, y, w) in edges:
			if find(x) != find(y):
				ans += w
				union(x, y)
		return ans


class UFDS:

	def __init__(self, n):
		self.p = list(range(n))

	def find(self, k):
		if self.p[k] == k:
			return k
		self.p[k] = self.find(self.p[k])
		return self.p[k]

	def issame(self, i, j):
		return self.find(i) == self.find(j)

	def union(self, i, j):
		(pi, pj) = (self.find(i), self.find(j))
		if pi == pj:
			return
		if pi < pj:
			self.p[pj] = pi
		else:
			self.p[pi] = pj

class Solution:

	def minCostConnectPoints(self, A: List[List[int]]) -> int:

		def dist(a, b):
			return abs(a[0] - b[0]) + abs(a[1] - b[1])
		n = len(A)
		dists = []
		for i in range(n):
			for j in range(i + 1, n):
				dists.append((dist(A[i], A[j]), (i, j)))
		dists.sort()
		ufds = UFDS(n)
		total = 0
		for (d, (i, j)) in dists:
			if not ufds.issame(i, j):
				total += d
				ufds.union(i, j)
		return total


class Solution:

	class UnionFinder:

		def __init__(self, n):
			self.parents = list(range(n))
			self.ranks = [0] * n

		def find(self, x):
			if self.parents[x] != x:
				self.parents[x] = self.find(self.parents[x])
			return self.parents[x]

		def join(self, x, y):
			p1 = self.find(x)
			p2 = self.find(y)
			if p1 == p2:
				return False
			r1 = self.ranks[p1]
			r2 = self.ranks[p2]
			if r1 < r2:
				self.parents[p1] = p2
			elif r2 < r1:
				self.parents[p2] = p1
			else:
				self.parents[p1] = p2
				self.ranks[p2] += 1
			return True

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		heap = list()
		cnt = 0
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				heapq.heappush(heap, (abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j))
		union_finder = Solution.UnionFinder(len(points))
		ans = 0
		while heap:
			(d, i, j) = heapq.heappop(heap)
			if union_finder.join(i, j):
				ans += d
				cnt += 1
				if cnt == len(points) - 1:
					break
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def hamin(a, b):
			return abs(a[0] - b[0]) + abs(a[1] - b[1])
		dist_list = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				dist_list.append([hamin(points[i], points[j]), i, j])
		dist_list = sorted(dist_list, key=lambda x: x[0])
		group_set = set()
		group_set.add(0)
		answer = 0
		while True:
			i = 0
			while i < len(dist_list):
				[dis, x, y] = dist_list[i]
				if x in group_set and y in group_set:
					dist_list.pop(i)
					continue
				if x in group_set:
					group_set.add(y)
					answer += dis
					break
				if y in group_set:
					group_set.add(x)
					answer += dis
					break
				i += 1
			if len(group_set) == len(points):
				break
		return answer


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		N = len(points)
		edges = []
		res = 0
		for i in range(N):
			for j in range(i + 1, N):
				distance = abs(points[i][0] - points[j][0])
				distance += abs(points[i][1] - points[j][1])
				edges.append((distance, i, j))
		edges.sort()
		unionfind = UnionFind(N)
		for edge in edges:
			(dis, i, j) = edge
			if unionfind.union(i, j):
				res += dis
		return res

class UnionFind:

	def __init__(self, n: int):
		self.parent = list(range(n))
		self.size = [1] * n

	def find(self, x):
		if self.parent[x] != x:
			self.parent[x] = self.find(self.parent[x])
		return self.parent[x]

	def union(self, x, y):
		(rx, ry) = (self.find(x), self.find(y))
		if rx == ry:
			return False
		if self.size[rx] < self.size[y]:
			(rx, ry) = (ry, rx)
		self.parent[ry] = rx
		self.size[rx] += self.size[ry]
		return True


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		dist = lambda x, y: abs(x[0] - y[0]) + abs(x[1] - y[1])
		neighbors = collections.defaultdict(dict)
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				neighbors[i][j] = dist(points[i], points[j])
				neighbors[j][i] = dist(points[i], points[j])
		pq = [(0, 0)]
		visited = set()
		res = 0
		while len(visited) < len(points):
			(d, u) = heapq.heappop(pq)
			if u in visited:
				continue
			print(d, u)
			res += d
			visited.add(u)
			for (v, d_) in neighbors[u].items():
				heapq.heappush(pq, (d_, v))
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		out = 0
		edges = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				edges += [(abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j)]
		edges = sorted(edges, key=lambda x: x[0])
		p = [i for i in range(len(points))]

		def findparent(i):
			if i != p[i]:
				p[i] = findparent(p[i])
			return p[i]
		for e in edges:
			p1 = findparent(e[1])
			p2 = findparent(e[2])
			if p1 != p2:
				p[p2] = p1
				out += e[0]
		return out


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		visited = [False] * n
		dist = collections.defaultdict(list)
		for i in range(n):
			(p1, p2) = points[i]
			for j in range(n):
				(x, y) = points[j]
				dist[i].append((abs(p1 - x) + abs(p2 - y), j))
		visited[0] = True
		hp = dist[0]
		heapq.heapify(hp)
		res = count = 0
		while hp:
			(cost, cur) = heapq.heappop(hp)
			if visited[cur]:
				continue
			visited[cur] = True
			res += cost
			count += 1
			if count == n - 1:
				break
			for d in dist[cur]:
				heapq.heappush(hp, d)
		return res


import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) < 1:
			return 0

		def dist(point1, point2):
			return abs(point1[0] - point2[0]) + abs(point1[1] - point2[1])
		heap = []
		connected = set([0])
		for (i, point) in enumerate(points):
			if i == 0:
				continue
			heapq.heappush(heap, (dist(point, points[0]), i, 0))
		res = 0
		while len(connected) != len(points):
			(dis, p, f) = heapq.heappop(heap)
			if p not in connected:
				res += dis
				connected.add(p)
			for (i, point) in enumerate(points):
				if i == p or i in connected:
					continue
				heapq.heappush(heap, (dist(point, points[p]), i, p))
		return res


class Solution:

	def minCostConnectPoints(self, p: List[List[int]]) -> int:

		def manhattan(x, y):
			return abs(x[0] - y[0]) + abs(x[1] - y[1])
		(ans, n) = (0, len(p))
		seen = set()
		import queue
		q = queue.PriorityQueue()
		q.put((0, (0, 0)))
		while len(seen) < n:
			(w, (u, v)) = q.get()
			if u in seen and v in seen:
				continue
			ans += w
			seen.add(v)
			for j in range(n):
				if j not in seen and j != v:
					q.put((manhattan(p[j], p[v]), (v, j)))
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		hq = []
		in_mst = [False] * len(points)

		def d(i: int, j: int) -> int:
			return abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])

		def add_to_hq(i: int):
			for j in range(len(points)):
				if i != j and (not in_mst[j]):
					heapq.heappush(hq, (d(i, j), j))
		heapq.heappush(hq, (0, 0))
		res = 0
		while hq:
			(dist, i) = heapq.heappop(hq)
			if not in_mst[i]:
				in_mst[i] = True
				res += dist
				add_to_hq(i)
		return res


from heapq import heappush, heappop

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		costs = sorted([(self.get_dist(points[i], points[j]), i, j) for i in range(n) for j in range(i)])
		groups = list(range(n))

		def find(node):
			while node != groups[node]:
				node = groups[node]
			return node
		res = 0
		for (cost, u, v) in costs:
			(root1, root2) = (find(u), find(v))
			if root1 != root2:
				res += cost
				groups[max(root1, root2)] = min(root1, root2)
		return res

	def get_dist(self, pt1, pt2):
		return abs(pt1[0] - pt2[0]) + abs(pt1[1] - pt2[1])


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		dis = collections.defaultdict(list)
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				d = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				dis[i].append((d, j))
				dis[j].append((d, i))
		(ans, seen, heap) = (0, set(), [(0, 0)])
		while len(seen) < len(points):
			(d, j) = heapq.heappop(heap)
			if j not in seen:
				seen.add(j)
				ans += d
				for (d, i) in dis[j]:
					heapq.heappush(heap, (d, i))
		return ans


from heapq import heappop, heappush

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		heap = []
		self.parent = {}
		self.count = {}
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				heappush(heap, (dist, i, j))
		result = 0
		while heap:
			(cur_dist, point1, point2) = heappop(heap)
			point1_parent = self.find(point1)
			point2_parent = self.find(point2)
			if point1_parent == point2_parent:
				continue
			self.parent[point1_parent] = point2_parent
			self.count[point2_parent] += self.count[point1_parent]
			result += cur_dist
			if self.count[point2_parent] == len(points):
				return result
		return 0

	def find(self, x):
		if x not in self.parent:
			self.parent[x] = x
			self.count[x] = 1
			return self.parent[x]
		if x == self.parent[x]:
			return self.parent[x]
		self.parent[x] = self.find(self.parent[x])
		return self.parent[x]


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		graph = collections.defaultdict(list)
		mh = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		for i in range(n):
			for j in range(i + 1, n):
				d = mh(points[i], points[j])
				graph[i].append((d, j))
				graph[j].append((d, i))
		cnt = 1
		ans = 0
		visited = [False] * n
		heap = graph[0]
		visited[0] = True
		heapq.heapify(heap)
		while heap:
			(d, j) = heapq.heappop(heap)
			if not visited[j]:
				visited[j] = True
				ans += d
				cnt += 1
				for nei in graph[j]:
					heapq.heappush(heap, nei)
			if cnt >= n:
				break
		return ans


class DisjointSet:

	def __init__(self, n):
		self.parent = list(range(n))

	def find(self, x):
		if self.parent[x] != x:
			self.parent[x] = self.find(self.parent[x])
		return self.parent[x]

	def union(self, x, y):
		(parx, pary) = (self.find(x), self.find(y))
		if parx == pary:
			return False
		self.parent[pary] = parx
		return True

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def distance(a, b):
			return abs(a[0] - b[0]) + abs(a[1] - b[1])
		edges = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				edges.append([distance(points[i], points[j]), i, j])
		edges.sort()
		dset = DisjointSet(len(points))
		res = numOfEdges = idx = 0
		while numOfEdges < len(points) - 1:
			(w, u, v) = edges[idx]
			if dset.union(u, v):
				res += w
				numOfEdges += 1
			idx += 1
		return res


class Solution:

	def minCostConnectPoints(self, a: List[List[int]]) -> int:
		n = len(a)
		if n <= 1:
			return 0
		d = dict()
		q = []
		for i in range(n - 1):
			(xi, yi) = a[i]
			for j in range(n):
				(xj, yj) = a[j]
				val = abs(xi - xj) + abs(yi - yj)
				d[i, j] = val
				d[j, i] = val
				q.append((val, i, j))

		def union(u, v):
			UF[find(v)] = UF[find(u)]

		def find(u):
			if u != UF[u]:
				UF[u] = find(UF[u])
			return UF[u]
		UF = {i: i for i in range(n)}
		ans = set()
		heapify(q)
		cur = set([q[0][1], q[0][2]])
		cand = []
		for x in cur:
			for y in range(n):
				if y in cur:
					continue
				cand.append((d[x, y], x, y))
		heapify(cand)
		ans = q[0][0]
		while len(cur) < n:
			(val, x, y) = heappop(cand)
			if find(x) != find(y):
				cur.add(y)
				union(x, y)
				ans += val
				for z in range(n):
					if z in cur:
						continue
					heappush(cand, (d[y, z], y, z))
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		d = collections.defaultdict(list)
		for i in range(n):
			for j in range(i + 1, n):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				d[i].append((dist, i, j))
				d[j].append((dist, j, i))
		chosen = {0}
		between = d[0].copy()
		heapq.heapify(between)
		res = 0
		while len(chosen) < n:
			(dist, i, j) = heapq.heappop(between)
			if i in chosen and j in chosen:
				continue
			elif i in chosen and j not in chosen:
				chosen.add(j)
				res += abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				for (jd, js, je) in d[j]:
					heapq.heappush(between, (jd, js, je))
			elif i not in chosen and j in chosen:
				chosen.add(i)
				res += abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				for (iid, iis, iie) in d[i]:
					heapq.heappush(between, (iid, iis, iie))
		return res


import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		mst_nodes = [0 for i in range(n)]
		mst_nodes_cnt = 0
		h = []
		man_dist = lambda i, j: abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
		mst_nodes[0] = 1
		for p in range(1, n):
			h.append((man_dist(0, p), 0, p))
		heapq.heapify(h)
		tot_dist = 0
		while h:
			(dist, src_node, dst_node) = heapq.heappop(h)
			if mst_nodes[dst_node]:
				continue
			tot_dist += dist
			mst_nodes[dst_node] = 1
			mst_nodes_cnt += 1
			if mst_nodes_cnt == n:
				break
			for next_dst in range(n):
				if mst_nodes[next_dst] == 0:
					heapq.heappush(h, (man_dist(dst_node, next_dst), dst_node, next_dst))
		return tot_dist


from collections import defaultdict
import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def manhattan(p1, p2):
			return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		n = len(points)
		c = defaultdict(list)
		for i in range(n):
			for j in range(i + 1, n):
				dist = manhattan(points[i], points[j])
				c[i].append((dist, j))
				c[j].append((dist, i))
		pq = c[0]
		heapq.heapify(pq)
		visited = [False] * n
		visited[0] = True
		cnt = 1
		res = 0
		while pq:
			(d, j) = heapq.heappop(pq)
			if not visited[j]:
				cnt += 1
				res += d
				visited[j] = True
				for record in c[j]:
					heapq.heappush(pq, record)
				if cnt >= n:
					break
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		edges = []
		connected = 1
		result = 0
		heapq.heapify(edges)
		visited = set()
		i = 0
		while connected < n:
			connected += 1
			visited.add(i)
			a = points[i]
			for j in range(n):
				b = points[j]
				if j not in visited:
					heapq.heappush(edges, (abs(a[0] - b[0]) + abs(a[1] - b[1]), j))
			while edges[0][1] in visited:
				heapq.heappop(edges)
			result += edges[0][0]
			i = heapq.heappop(edges)[1]
		return result


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		edge_costs = []
		for i in range(n):
			for j in range(i + 1, n):
				(p1, p2) = (points[i], points[j])
				cost = abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
				edge_costs.append((cost, (i, j)))
		edge_costs.sort()
		total = 0
		parent = list(range(n))

		def find_parent(v):
			if parent[v] == v:
				return v
			else:
				parent[v] = find_parent(parent[v])
				return parent[v]
		for (cost, edge) in edge_costs:
			(v1, v2) = edge
			v1_parent = find_parent(v1)
			v2_parent = find_parent(v2)
			if v1_parent != v2_parent:
				total += cost
				parent[v2_parent] = v1_parent
		return total


class UF:

	def __init__(self, n):
		self.root = [i for i in range(n)]

	def find(self, a):
		if self.root[a] != a:
			self.root[a] = self.find(self.root[a])
		return self.root[a]

	def unite(self, a, b):
		self.root[self.find(a)] = self.find(b)

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		(edges, res) = ([], 0)
		for i in range(n):
			for j in range(i + 1, n):
				edges.append([abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j])
		edges.sort()
		uf = UF(n)
		for (w, s, t) in edges:
			if uf.find(s) != uf.find(t):
				uf.unite(s, t)
				res += w
		return res


class DSU:

	def __init__(self, N):
		self.parent = [i for i in range(N)]
		self.size = [1] * N

	def find(self, x):
		if self.parent[x] == x:
			return x
		return self.find(self.parent[x])

	def union(self, x, y):
		(par_x, par_y) = (self.find(x), self.find(y))
		if par_x == par_y:
			return False
		if self.size[par_x] < self.size[par_y]:
			(par_x, par_y) = (par_y, par_x)
		self.parent[par_y] = par_x
		self.size[par_x] += self.size[par_y]
		self.size[par_y] = self.size[par_x]
		return True

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []
		N = len(points)
		if not points:
			return -1
		for i in range(N):
			for j in range(i + 1, N):
				(x1, y1) = points[i]
				(x2, y2) = points[j]
				d = abs(x1 - x2) + abs(y1 - y2)
				edges.append([i, j, d])
		UF = DSU(N)
		total_cost = 0
		edges.sort(key=lambda x: x[2])
		for (i, j, d) in edges:
			if UF.union(i, j):
				total_cost += d
		return total_cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		N = len(points)
		G = collections.defaultdict(list)
		for i in range(N):
			for j in range(N):
				if i == j:
					continue
				cost_x = abs(points[i][0] - points[j][0])
				cost_y = abs(points[i][1] - points[j][1])
				cost = cost_x + cost_y
				G[i].append((cost, j))
				G[j].append((cost, i))
		PQ = []
		SEEN = set()

		def add(u):
			SEEN.add(u)
			for (cost, v) in G[u]:
				if v in SEEN:
					continue
				heapq.heappush(PQ, (cost, v))
		mst = 0
		add(0)
		while PQ and len(SEEN) < N:
			(cost, u) = heapq.heappop(PQ)
			if u in SEEN:
				continue
			mst += cost
			add(u)
		return mst


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def cost(i, j):
			return abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
		n = len(points)
		dists = []
		for i in range(n):
			for j in range(i + 1, n):
				dists.append((cost(i, j), i, j))
		dists.sort()
		uf = UnionFind(n)
		ans = 0
		for (c, i, j) in dists:
			if uf.union(i, j):
				ans += c
		return ans

class UnionFind:

	def __init__(self, n):
		self.id = [i for i in range(n)]
		self.size = [1 for _ in range(n)]

	def find(self, i):
		root = i
		while root != self.id[root]:
			root = self.id[root]
		while root != i:
			j = self.id[i]
			self.id[i] = root
			i = j
		return root

	def union(self, i, j):
		root_i = self.find(i)
		root_j = self.find(j)
		if root_i == root_j:
			return False
		if self.size[root_i] < self.size[root_j]:
			self.id[root_i] = root_j
			self.size[root_j] += self.size[root_i]
		else:
			self.id[root_j] = root_i
			self.size[root_i] += self.size[root_j]
		return True


class UnionFind:

	def __init__(self):
		self.parent = {}
		self.size = {}

	def makeset(self, point):
		self.parent[point] = point
		self.size[point] = 1

	def find(self, point):
		if self.parent[point] == point:
			return point
		self.parent[point] = self.find(self.parent[point])
		return self.parent[point]

	def union(self, point1, point2):
		point1 = self.find(point1)
		point2 = self.find(point2)
		if point1 == point2:
			return (False, self.size[point1])
		self.parent[point2] = point1
		self.size[point1] += self.size[point2]
		return (True, self.size[point1])

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		costmetrics = []
		unionfind = UnionFind()
		for point in points:
			unionfind.makeset(tuple(point))
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				cost = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				costmetrics.append([cost, tuple(points[i]), tuple(points[j])])
		costmetrics.sort(key=lambda item: item[0])
		ans = 0
		for i in range(len(costmetrics)):
			(res, sz) = unionfind.union(costmetrics[i][1], costmetrics[i][2])
			if res:
				ans += costmetrics[i][0]
			if sz == len(points):
				break
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		dis = []
		d = {}
		u = {}
		for (i, x) in enumerate(points):
			d[i] = 0
			u[i] = i
			for y in range(i + 1, len(points)):
				z = points[y]
				m = abs(x[0] - z[0]) + abs(x[1] - z[1])
				dis.append([m, i, y])

		def merge(c1, c2):
			if u[c1] > u[c2]:
				(c1, c2) = (c2, c1)
			t = u[c2]
			for (k, v) in u.items():
				if v == t:
					u[k] = u[c1]
		dis = sorted(dis)
		c = 0
		result = 0
		count = 0
		while count < len(points) - 1:
			while 1:
				(c0, c1, c2) = dis[c]
				if u[c1] != u[c2]:
					merge(c1, c2)
					d[c1] += 1
					d[c2] += 1
					count += 1
					result += c0
					c += 1
					break
				c += 1
		return result


class Solution:

	def minCostConnectPoints(self, p: List[List[int]]) -> int:
		n = len(p)
		a = [i for i in range(n + 1)]
		rank = [0 for i in range(n + 1)]

		def find(i):
			if i == a[i]:
				return i
			a[i] = find(a[i])
			return a[i]

		def union(x, y):
			xs = find(x)
			ys = find(y)
			if xs != ys:
				if rank[ys] > rank[xs]:
					(ys, xs) = (xs, ys)
				a[ys] = xs
				rank[xs] += 1
				return 1
			return 0
		edge = []
		for i in range(n):
			for j in range(i + 1, n):
				dis = abs(p[i][0] - p[j][0]) + abs(p[i][1] - p[j][1])
				edge.append([dis, i, j])
		ans = 0
		edge.sort()
		for (dis, i, j) in edge:
			if union(i, j):
				ans += dis
		return ans


from heapq import heappush

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		visited = set()
		minCost = 0
		minEdges = []
		heappush(minEdges, (0, 0))
		while len(visited) < len(points):
			(vertexDistance, vertexIdx) = heappop(minEdges)
			if vertexIdx in visited:
				continue
			print(vertexIdx)
			visited.add(vertexIdx)
			minCost += vertexDistance
			vertexX = points[vertexIdx][0]
			vertexY = points[vertexIdx][1]
			for (adjIdx, adjPos) in enumerate(points):
				if adjIdx not in visited:
					adjX = points[adjIdx][0]
					adjY = points[adjIdx][1]
					distance = abs(vertexX - adjX) + abs(vertexY - adjY)
					heappush(minEdges, (distance, adjIdx))
		return minCost


import math

class DSU:

	def __init__(self, n):
		self.n = n
		self.parent = [i for i in range(n)]

	def find(self, x):
		while self.parent[x] != x:
			x_p = self.parent[x]
			self.parent[x] = self.parent[x_p]
			x = self.parent[x]
		return x

	def union(self, x, y):
		x_p = self.find(x)
		y_p = self.find(y)
		if x_p != y_p:
			self.parent[x_p] = y_p

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []
		for i in range(len(points)):
			for j in range(len(points)):
				dist = self.distance(points[i], points[j])
				edges.append((dist, i, j))
		edges = sorted(edges, key=lambda x: x[0])
		ans = 0
		n = len(points)
		dsu = DSU(n)
		i = 0
		j = 0
		while i < n - 1:
			(dist, a, b) = edges[j]
			a_p = dsu.find(a)
			b_p = dsu.find(b)
			if a_p != b_p:
				dsu.union(a, b)
				i += 1
				ans += dist
			j += 1
		return ans

	def distance(self, p1, p2):
		return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])


class Graph:

	def __init__(self, vertices):
		self.V = vertices
		self.graph = []

	def addEdge(self, u, v, w):
		self.graph.append([u, v, w])

	def find(self, parent, i):
		if parent[i] == i:
			return i
		return self.find(parent, parent[i])

	def union(self, parent, rank, x, y):
		xroot = self.find(parent, x)
		yroot = self.find(parent, y)
		if rank[xroot] < rank[yroot]:
			parent[xroot] = yroot
		elif rank[xroot] > rank[yroot]:
			parent[yroot] = xroot
		else:
			parent[yroot] = xroot
			rank[xroot] += 1

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		result = 0
		i = 0
		e = 0
		g = Graph(len(points))
		for i in range(len(points) - 1):
			for j in range(i, len(points)):
				a = tuple(points[i])
				b = tuple(points[j])
				g.addEdge(a, b, abs(a[0] - b[0]) + abs(a[1] - b[1]))
		g.graph = sorted(g.graph, key=lambda item: item[2])
		parent = [0] * g.V
		rank = [0] * g.V
		dic = {}
		for (i, p) in enumerate(points):
			dic[tuple(p)] = i
		for i in range(g.V):
			parent[i] = i
		while e < g.V - 1:
			(u, v, w) = g.graph[i]
			i = i + 1
			x = g.find(parent, dic[u])
			y = g.find(parent, dic[v])
			if x != y:
				e = e + 1
				result += w
				g.union(parent, rank, x, y)
		return result


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def find(i):
			while i != root[i]:
				root[i] = root[root[i]]
				i = root[i]
			return i
		(res, n) = (0, len(points))
		(conn, root) = ([], [i for i in range(n)])
		for i in range(n):
			for j in range(i + 1, n):
				conn.append([i, j, abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])])
		conn.sort(key=lambda c: c[2])
		for c in conn:
			p1 = find(c[0])
			p2 = find(c[1])
			if p1 != p2:
				res += c[2]
				root[p1] = p2
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		parents = list(range(len(points)))

		def find(x):
			if parents[x] != x:
				parents[x] = find(parents[x])
			return parents[x]

		def union(x, y):
			px = find(x)
			py = find(y)
			if px != py:
				parents[py] = px
				return False
			return True
		edges = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				edges.append((dist, i, j))
		edges.sort()
		ans = 0
		for (w, x, y) in edges:
			if not union(x, y):
				ans += w
		return ans


class DSU:

	def __init__(self, n):
		self.parents = list(range(n))

	def find(self, u):
		orig = u
		while u != self.parents[u]:
			u = self.parents[u]
		self.parents[orig] = u
		return u

	def union(self, u, v):
		(u, v) = sorted([self.find(u), self.find(v)])
		if u != v:
			self.parents[v] = u
			return True
		return False

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		distances = {}

		def compute(p1, p2):
			(x1, y1) = p1
			(x2, y2) = p2
			return abs(x1 - x2) + abs(y1 - y2)
		for (i, p1) in enumerate(points):
			for j in range(i + 1, len(points)):
				p2 = points[j]
				distances[i, j] = compute(p1, p2)
		dsu = DSU(len(points))
		res = 0
		for ((u, v), d) in sorted(list(distances.items()), key=lambda x: x[1]):
			if dsu.union(u, v):
				res += d
		return res


from collections import defaultdict
import heapq

class Solution:

	def minCostConnectPoints(self, points) -> int:
		edges = defaultdict(list)
		n = len(points)
		connected_pts = set([0])
		pending_edges = []
		for i in range(n):
			for j in range(i + 1, n):
				w = abs(points[j][1] - points[i][1]) + abs(points[j][0] - points[i][0])
				edges[i].append((w, j))
				edges[j].append((w, i))
		for e in edges[0]:
			heapq.heappush(pending_edges, (e[0], e[1]))
		res = 0
		while len(connected_pts) < n:
			found_edge = False
			while not found_edge:
				e = heapq.heappop(pending_edges)
				if e[1] in connected_pts:
					continue
				found_edge = True
				connected_pts.add(e[1])
				res += e[0]
				for next_edge in edges[e[1]]:
					if next_edge not in connected_pts:
						heapq.heappush(pending_edges, (next_edge[0], next_edge[1]))
		return res


from functools import cmp_to_key

def cmp(a, b):
	return a[2] - b[2]

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []
		points = [tuple(l) for l in points]
		N = len(points)
		if N == 1:
			return 0
		for i in range(N):
			(x, y) = points[i]
			for j in range(i + 1, N):
				(x1, y1) = points[j]
				edges.append((i, j, abs(x - x1) + abs(y - y1)))
		edges.sort(key=cmp_to_key(cmp))
		parent = {i: i for i in points}
		rank = {i: 0 for i in points}
		val = 0
		ct = 0
		for (i, j, v) in edges:
			l = self.union(rank, parent, points[i], points[j])
			if l != 0:
				ct += 1
				val += v
			if ct == N - 1:
				return val

	def find(self, parent, node):
		if parent[node] == node:
			return node
		parent[node] = self.find(parent, parent[node])
		return parent[node]

	def union(self, rank, parent, node1, node2):
		x = self.find(parent, node1)
		y = self.find(parent, node2)
		if x == y:
			return 0
		if rank[x] > rank[y]:
			parent[y] = x
		elif rank[x] < rank[y]:
			parent[x] = y
		else:
			rank[x] += 1
			parent[y] = x
		return 1


import heapq

class DisjointSet:

	def __init__(self, n):
		self.parent = [i for i in range(n)]
		self.rank = [1] * n
		self.maxRank = 1

	def union(self, a, b):
		pa = self.find(a)
		pb = self.find(b)
		if pa == pb:
			return
		if self.rank[pa] > self.rank[pb]:
			self.parent[pb] = pa
			self.rank[pa] += self.rank[pb]
			self.maxRank = max(self.maxRank, self.rank[pa])
		else:
			self.parent[pa] = pb
			self.rank[pb] += self.rank[pa]
			self.maxRank = max(self.maxRank, self.rank[pb])

	def find(self, a):
		if self.parent[a] == a:
			return a
		self.parent[a] = self.find(self.parent[a])
		return self.parent[a]

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def distance(u, v):
			dx = abs(u[0] - v[0])
			dy = abs(u[1] - v[1])
			return dx + dy
		n = len(points)
		if n == 1:
			return 0
		if n == 2:
			return distance(points[0], points[1])
		edges = []
		for i in range(n):
			for j in range(i + 1, n):
				dist = distance(points[i], points[j])
				edges.append((dist, i, j))
		heapq.heapify(edges)
		cost = 0
		ds = DisjointSet(n)
		while ds.maxRank < n:
			(dist, u, v) = heapq.heappop(edges)
			if ds.find(u) != ds.find(v):
				cost += dist
				ds.union(u, v)
		return cost


from collections import defaultdict
from heapq import heappush, heappop

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		G = defaultdict(dict)
		for (i, (xi, yi)) in enumerate(points):
			for (j, (xj, yj)) in enumerate(points[i + 1:], i + 1):
				d = abs(xi - xj) + abs(yi - yj)
				G[i][j] = G[j][i] = d
		(seen, pq, ans) = ({0}, [], 0)
		for (nb, d) in G[0].items():
			heappush(pq, (d, nb))
		while len(seen) < len(G):
			while pq:
				(cost, next_node) = heappop(pq)
				if next_node in seen:
					continue
				seen.add(next_node)
				ans += cost
				for (nb, d) in G[next_node].items():
					if nb in seen:
						continue
					heappush(pq, (d, nb))
		return ans


class UnionFind:

	def __init__(self, n):
		self.parent = [i for i in range(n)]
		self.rank = [1 for _ in range(n)]

	def union(self, i, j):
		x = self.find(i)
		y = self.find(j)
		if x == y:
			return
		if self.rank[x] > self.rank[y]:
			self.parent[y] = x
			self.rank[x] += self.rank[y]
		else:
			self.parent[x] = y
			self.rank[y] += self.rank[x]

	def find(self, i):
		if self.parent[i] == i:
			return self.parent[i]
		return self.find(self.parent[i])

class Solution:

	def minCostConnectPoints(self, points) -> int:
		n = len(points)
		edges = []
		for i in range(n):
			for j in range(i + 1, n):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				edges.append((dist, i, j))
		edges.sort()
		res = 0
		uf = UnionFind(n)
		for (cost, u, v) in edges:
			if uf.find(u) != uf.find(v):
				uf.union(u, v)
				res += cost
		return res


class uf(object):

	def __init__(self, n):
		self.parent = [i for i in range(n)]
		self.rank = [1 for i in range(n)]

	def union(self, x, y):
		(p1, p2) = (self.find(x), self.find(y))
		if self.rank[p1] == self.rank[p2]:
			self.parent[p2] = p1
			self.rank[p1] += 1
		elif self.rank[p1] > self.rank[p2]:
			self.parent[p2] = p1
		else:
			self.parent[p1] = p2
		return

	def find(self, x):
		if self.parent[x] == x:
			return x
		return self.find(self.parent[x])

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []
		union_find = uf(len(points))
		ans = 0
		n = len(points)
		for i in range(n):
			for j in range(i + 1, n):
				edges.append((abs(points[j][0] - points[i][0]) + abs(points[j][1] - points[i][1]), i, j))
		edges = sorted(edges)
		for (w, u, v) in edges:
			if union_find.find(u) != union_find.find(v):
				union_find.union(u, v)
				ans += w
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		dist = []
		for (i, p1) in enumerate(points):
			for (j, p2) in enumerate(points):
				if i != j:
					d = abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
					heapq.heappush(dist, (d, i, j))
		g = defaultdict(set)
		checked = set()

		def connected(a, b):
			if b in g[a]:
				return True
			if a in checked:
				return False
			checked.add(a)
			for p in g[a]:
				if connected(p, b):
					return True
			return False
		conn = 0
		d = 0
		while conn < len(points) - 1:
			p = heapq.heappop(dist)
			checked = set()
			if not connected(p[1], p[2]):
				g[p[2]].add(p[1])
				g[p[1]].add(p[2])
				d += p[0]
				conn += 1
		return d


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		all_edges = []
		for point1 in points:
			for point2 in points:
				if point1 != point2:
					all_edges.append((abs(point1[0] - point2[0]) + abs(point1[1] - point2[1]), tuple(point1), tuple(point2)))
		all_edges.sort(key=lambda x: x[0])
		parent = {tuple(point): tuple(point) for point in points}
		rank = {tuple(point): 1 for point in points}
		children = {tuple(point): 1 for point in points}

		def find(point1):
			if parent[point1] != point1:
				parent[point1] = find(parent[point1])
			return parent[point1]

		def union(point1, point2):
			parent1 = find(point1)
			parent2 = find(point2)
			if rank[parent1] > rank[parent2]:
				parent[parent2] = parent1
				rank[parent1] += 1
				children[parent1] += children[parent2]
			else:
				parent[parent1] = parent2
				rank[parent2] += 1
				children[parent2] += children[parent1]
			return
		cost = 0
		count = 0
		for edge in all_edges:
			if count == len(points) - 1:
				break
			if find(edge[1]) != find(edge[2]):
				union(edge[1], edge[2])
				cost += edge[0]
				count += 1
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		connections = []
		self.father = {}
		self.size = n
		for i in range(n):
			self.father[points[i][0], points[i][1]] = (points[i][0], points[i][1])
			for j in range(i + 1, n):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				p1 = (points[i][0], points[i][1])
				p2 = (points[j][0], points[j][1])
				connections.append((p1, p2, dist))
		connections = sorted(connections, key=lambda x: x[2])
		res = 0

		def union(a, b):
			root_a = find(a)
			root_b = find(b)
			if root_a != root_b:
				self.father[root_a] = root_b
				self.size -= 1
				return True
			else:
				return False

		def find(node):
			path = []
			while node != self.father[node]:
				path.append(node)
				node = self.father[node]
			for child in path:
				self.father[child] = node
			return node
		for c in connections:
			if union(c[0], c[1]):
				res += c[2]
				if self.size == 0:
					return res
		return res


class DSU:

	def __init__(self, n):
		self.parent = [i for i in range(n)]
		self.rank = [1 for i in range(n)]
		self.count = n

	def find(self, x):
		if x != self.parent[x]:
			self.parent[x] = self.find(self.parent[x])
		return self.parent[x]

	def union(self, x, y):
		px = self.find(x)
		py = self.find(y)
		if px == py:
			return False
		self.count -= 1
		if self.rank[x] > self.rank[y]:
			self.parent[py] = px
			self.rank[px] += self.rank[py]
		else:
			self.parent[px] = py
			self.rank[py] += self.rank[px]
		return True

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		edges = []
		for i in range(n):
			for j in range(i + 1, n):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				heapq.heappush(edges, (dist, i, j))
		res = 0
		ds = DSU(n)
		while edges and ds.count != 1:
			(cost, u, v) = heapq.heappop(edges)
			if ds.union(u, v):
				res += cost
		return res


class UnionFind:

	def __init__(self):
		self.roots = {}
		self.depth = {}

	def root(self, node):
		if node not in self.roots:
			self.roots[node] = node
			self.depth[node] = 1
		path = []
		while self.roots[node] != node:
			path.append(node)
			node = self.roots[node]
		for elem in path:
			self.roots[elem] = node
		return node

	def connect(self, x, y):
		x = self.root(x)
		y = self.root(y)
		if x == y:
			return
		if self.depth[x] > self.depth[y]:
			(x, y) = (y, x)
		if self.depth[x] == self.depth[y]:
			new_depth = self.depth[y] + 1
		else:
			new_depth = self.depth[y]
		del self.depth[x]
		self.roots[x] = y
		self.depth[y] = new_depth

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		min_span_tree = UnionFind()
		cost = 0
		edges = []
		for i in range(1, len(points)):
			for j in range(i):
				edge_cost = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				edges.append([edge_cost, i, j])
		edges.sort()
		to_connect = len(points) - 1
		for (edge_cost, i, j) in edges:
			if not to_connect:
				break
			if min_span_tree.root(i) != min_span_tree.root(j):
				cost += edge_cost
				min_span_tree.connect(i, j)
				to_connect -= 1
		return cost


class Graph:

	def __init__(self, v=0):
		self.v = v
		self.edge = []

class UnionFind:

	def __init__(self, n):
		self.parent = [i for i in range(n)]
		self.rank = [0] * n

	def find(self, i):
		if self.parent[i] != i:
			self.parent[i] = self.find(self.parent[i])
		return self.parent[i]

	def union(self, u, v):
		(uroot, vroot) = (self.find(u), self.find(v))
		if uroot == vroot:
			return False
		elif self.rank[uroot] < self.rank[vroot]:
			self.parent[uroot] = vroot
			self.rank[vroot] += 1
		else:
			self.parent[vroot] = uroot
			self.rank[uroot] += 1
		return True

class Solution:

	def distance(self, point1: List[int], point2: List[int]):
		return abs(point1[0] - point2[0]) + abs(point1[1] - point2[1])

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if not points or len(points) < 2:
			return 0
		n = len(points)
		graph = Graph(n)
		tot = 0
		for i in range(n):
			for j in range(i + 1, n):
				d = self.distance(points[i], points[j])
				graph.edge.append([i, j, d])
		graph.edge = sorted(graph.edge, key=lambda item: item[2])
		uf = UnionFind(n)
		for (u, v, w) in graph.edge:
			if uf.union(u, v):
				tot += w
		return tot


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		cost_map = {}
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				cost = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				cost_map[i, j] = cost
		graph = []
		for (key, value) in cost_map.items():
			graph.append([key[0], key[1], value])

		def find(city):
			if parent[city] != city:
				parent[city] = find(parent[city])
			return parent[city]

		def union(city1, city2):
			root1 = find(city1)
			root2 = find(city2)
			if root1 == root2:
				return False
			parent[root2] = root1
			return True
		parent = {city: city for city in range(0, len(points))}
		graph.sort(key=lambda x: x[2])
		totalCost = 0
		for (city1, city2, cost) in graph:
			if union(city1, city2):
				totalCost += cost
		root = find(len(points) - 1)
		for i in range(0, len(points)):
			if find(i) == root:
				continue
			else:
				return -1
		return totalCost


from heapq import *

class Solution:

	def minCostConnectPoints(self, points):
		N = len(points)
		parent = [i for i in range(N)]

		def find(v):
			while parent[v] != parent[parent[v]]:
				parent[v] = parent[parent[v]]
			return parent[v]
		(heap, total_cost) = ([], 0)
		for (i1, p1) in enumerate(points):
			for (i2, p2) in enumerate(points[i1 + 1:], start=i1 + 1):
				heappush(heap, (abs(p1[0] - p2[0]) + abs(p1[1] - p2[1]), i1, i2))
		while heap:
			(cost, u, v) = heappop(heap)
			(pu, pv) = (find(u), find(v))
			if pu != pv:
				parent[pu] = pv
				N -= 1
				total_cost += cost
				if N == 0:
					break
		return total_cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []
		nodes = set()
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				dis = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				edges.append((dis, i, j))
				nodes.add(i)
				nodes.add(j)

		class UnionFindSet:

			def __init__(self, nodes):
				self._parents = {}
				self._ranks = {}
				for n in nodes:
					self._parents[n] = n
					self._ranks[n] = 1

			def find(self, u):
				while u != self._parents[u]:
					self._parents[u] = self.find(self._parents[u])
					u = self._parents[u]
				return u

			def union(self, u, v):
				(pu, pv) = (self.find(u), self.find(v))
				if pu == pv:
					return False
				if self._ranks[pu] < self._ranks[pv]:
					self._parents[pu] = pv
				elif self._ranks[pu] > self._ranks[pv]:
					self._parents[pv] = pu
				else:
					self._parents[pv] = pu
					self._ranks[pu] += 1
				return True
		uf = UnionFindSet(nodes)
		edges.sort()
		cost = 0
		for (dis, u, v) in edges:
			(pu, pv) = (uf.find(u), uf.find(v))
			if pu == pv:
				continue
			else:
				cost += dis
				uf.union(u, v)
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		dist = []
		for x in range(len(points)):
			[xi, yi] = points[x]
			for y in range(x + 1, len(points)):
				[xj, yj] = points[y]
				manhattan_dist = abs(xi - xj) + abs(yi - yj)
				if x != y:
					dist.append([x, y, manhattan_dist])
		dist.sort(key=lambda pt: pt[2])

		def detectCycle(adj):
			visited = set()

			def dfs(curr, parent):
				visited.add(curr)
				for neighbor in adj[curr]:
					if neighbor == parent:
						continue
					elif neighbor in visited:
						return True
					elif dfs(neighbor, curr):
						return True
				return False
			for node in range(len(points)):
				if node not in visited:
					if dfs(node, -1):
						return True
			return False
		adj = {x: set() for x in range(len(points))}
		ans = 0
		v = 0
		for distance in dist:
			[x, y, manhattan_dist] = distance
			adj[x].add(y)
			adj[y].add(x)
			if detectCycle(adj):
				adj[x].remove(y)
				adj[y].remove(x)
			else:
				ans += manhattan_dist
				v += 1
			if v == len(points) - 1:
				break
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def calc(x, y):
			return abs(x[0] - y[0]) + abs(x[1] - y[1])
		connections = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				if i != j:
					connections.append([i, j, calc(points[i], points[j])])
		connections.sort(key=lambda x: x[2])
		n = len(points)
		parent = [-1] * n
		size = [1] * n
		res = []

		def find(x):
			if parent[x] == -1:
				return x
			parent[x] = find(parent[x])
			return parent[x]

		def union(x, y):
			px = find(x)
			py = find(y)
			if px == py:
				return False
			if size[px] > size[py]:
				size[px] += size[py]
				parent[py] = px
			else:
				size[py] += size[px]
				parent[px] = py
			return True
		for (s, d, w) in connections:
			if union(s, d):
				res.append([s, d, w])
		ans = 0
		for (a, b, c) in res:
			ans += c
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		g = [[] for _ in range(n)]
		for i in range(n - 1):
			(x0, y0) = points[i]
			for j in range(i + 1, n):
				(x1, y1) = points[j]
				d = abs(x0 - x1) + abs(y0 - y1)
				g[i].append((d, j))
				g[j].append((d, i))
		import heapq

		def prim_heap(edge):
			used = [True] * n
			edgelist = []
			for e in edge[0]:
				heapq.heappush(edgelist, e)
				used[0] = False
			res = 0
			while len(edgelist) != 0:
				minedge = heapq.heappop(edgelist)
				if not used[minedge[1]]:
					continue
				v = minedge[1]
				used[v] = False
				for e in edge[v]:
					if used[e[1]]:
						heapq.heappush(edgelist, e)
				res += minedge[0]
			return res
		res = prim_heap(g)
		return res


class Unifind:

	def __init__(self, n):
		self.arr = list(range(n))
		self.rank = [0] * n

	def union(self, a, b):
		a = self.find(a)
		b = self.find(b)
		if self.rank[a] < self.rank[b]:
			(a, b) = (b, a)
		if self.rank[a] == self.rank[b]:
			self.rank[a] += 1
		self.arr[b] = a

	def find(self, a):
		if self.arr[a] != a:
			self.arr[a] = self.find(self.arr[a])
		return self.arr[a]

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		manhatan = lambda x1, y1, x2, y2: (x1 - x2 if x1 > x2 else x2 - x1) + (y1 - y2 if y1 > y2 else y2 - y1)
		edges = [(manhatan(points[i][0], points[i][1], points[j][0], points[j][1]), i, j) for i in range(len(points)) for j in range(i + 1, len(points))]
		heapify(edges)
		uf = Unifind(len(points))
		count = 0
		cost = 0
		while count < len(points) - 1:
			(c, i, j) = heappop(edges)
			if uf.find(i) != uf.find(j):
				cost += c
				count += 1
				uf.union(i, j)
		return cost


class DSU:

	def __init__(self, N):
		self.par = list(range(N))
		self.sz = [1] * N

	def find(self, x):
		if self.par[x] != x:
			self.par[x] = self.find(self.par[x])
		return self.par[x]

	def union(self, x, y):
		(xr, yr) = (self.find(x), self.find(y))
		if xr == yr:
			return False
		if self.sz[xr] < self.sz[yr]:
			(xr, yr) = (yr, xr)
		self.par[yr] = xr
		self.sz[xr] += self.sz[yr]
		return True

class Solution:

	def minCostConnectPoints(self, points):
		N = len(points)
		edges = []
		for i in range(N):
			for j in range(i + 1, N):
				d = abs(points[i][0] - points[j][0])
				d += abs(points[i][1] - points[j][1])
				edges.append([d, i, j])
		edges.sort()
		ans = 0
		dsu = DSU(N)
		for (d, u, v) in edges:
			if dsu.union(u, v):
				ans += d
		return ans


from heapq import *

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		result = 0
		if len(points) == 1:
			return result
		costHeap = []
		n = len(points)
		cur = 0
		distance = lambda p, np: abs(p[0] - np[0]) + abs(p[1] - np[1])
		visited = [False for _ in range(n)]
		visited[0] = True
		size = 1
		for i in range(1, n):
			heappush(costHeap, [distance(points[0], points[i]), i])
		while costHeap:
			(cost, nextStart) = heappop(costHeap)
			if not visited[nextStart]:
				result += cost
				visited[nextStart] = True
				size += 1
				cur = nextStart
				for i in range(n):
					heappush(costHeap, [distance(points[cur], points[i]), i])
				if size == n:
					break
		return result


class DSU:

	def __init__(self, n):
		self.p = list(range(n))

	def find(self, x):
		if self.p[x] != x:
			self.p[x] = self.find(self.p[x])
		return self.p[x]

	def union(self, x, y):
		p_x = self.find(x)
		p_y = self.find(y)
		if p_x != p_y:
			self.p[p_x] = p_y
			return True
		return False

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		if n < 2:
			return 0

		def dist(p1, p2):
			return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		dic = {}
		for i in range(n):
			for j in range(i + 1, n):
				dic[i, j] = dist(points[i], points[j])
		o = sorted(list(dic.items()), key=lambda v: v[1])
		dsu = DSU(n)
		res = 0
		for (pts, cost) in o:
			(p1, p2) = pts
			if dsu.union(p1, p2):
				res += cost
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []
		sets = list(range(len(points)))
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				d = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				edges.append([d, i, j])
		edges.sort()
		n_edges = 0
		ans = 0
		cur = 0

		def find(i):
			while sets[i] != i:
				i = sets[i]
			return i
		while n_edges != len(sets) - 1:
			(d, i, j) = edges[cur]
			if find(i) != find(j):
				sets[find(i)] = find(j)
				ans += d
				n_edges += 1
			cur += 1
		return ans


import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def helper(a, b):
			return abs(a[0] - b[0]) + abs(a[1] - b[1])
		edges = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				heapq.heappush(edges, (helper(points[i], points[j]), i, j))
		tree = []
		res = 0
		while edges:
			(dist, i, j) = heapq.heappop(edges)
			flag = False
			for p in range(len(tree)):
				s = tree[p]
				if i in s or j in s:
					q = j if i in s else i
					if q not in s:
						set_num = -1
						for k in range(len(tree)):
							st = tree[k]
							if q in st:
								set_num = k
								break
						if set_num != -1:
							tree[p] = tree[p].union(tree[k])
							tree.pop(k)
						else:
							s.add(q)
						res += dist
					flag = True
					break
			if not flag:
				tree.append({i, j})
				res += dist
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		parent = list(range(n))
		rank = [0] * n

		def find(x):
			while parent[x] != x:
				x = parent[x]
			return x

		def union(x, y):
			id_x = find(x)
			id_y = find(y)
			if id_x == id_y:
				return 0
			if rank[id_x] == rank[id_y]:
				parent[id_y] = id_x
				rank[id_x] += 1
			elif rank[id_x] > rank[id_y]:
				parent[id_y] = id_x
			else:
				parent[id_x] = id_y
			return 1
		edges = []
		for i in range(n):
			for j in range(i + 1, n):
				edges.append((abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j))
		edges = sorted(edges, key=lambda x: x[0])
		cost = 0
		for edge in edges:
			if union(edge[1], edge[2]):
				cost += edge[0]
		return cost


class dsu:

	def __init__(self, n):
		self.parent = [-1 for i in range(n)]
		self.size = [0 for i in range(n)]

	def make_set(self, node):
		self.parent[node] = node

	def find(self, a):
		if self.parent[a] == a:
			return self.parent[a]
		else:
			self.parent[a] = self.find(self.parent[a])
			return self.parent[a]

	def union(self, a, b):
		a = self.find(a)
		b = self.find(b)
		if a != b:
			self.parent[b] = self.parent[a]

class Solution:

	def minCostConnectPoints(self, p: List[List[int]]) -> int:
		n = len(p)
		if n <= 1:
			return 0
		tree = dsu(n)
		edges = []
		for i in range(len(p)):
			for j in range(i + 1, len(p)):
				edges.append([abs(p[i][0] - p[j][0]) + abs(p[i][1] - p[j][1]), i, j])
		edges.sort()
		done = 0
		ans = 0
		for i in range(n):
			tree.make_set(i)
		for i in edges:
			if tree.find(i[1]) != tree.find(i[2]):
				done = done + 1
				ans = ans + i[0]
				tree.union(i[1], i[2])
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		graph = defaultdict(list)
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				(x1, y1) = points[i]
				(x2, y2) = points[j]
				manhattan_dist = abs(x1 - x2) + abs(y1 - y2)
				graph[i].append((manhattan_dist, j))
				graph[j].append((manhattan_dist, i))
		visited = set()
		heap = [(0, 0)]
		cost = 0
		while heap:
			(distance, current_node) = heapq.heappop(heap)
			if current_node not in visited:
				visited.add(current_node)
				cost += distance
				for (dist, neigh) in graph[current_node]:
					if neigh not in visited:
						heapq.heappush(heap, (dist, neigh))
		return cost


class DSU:

	def __init__(self, n):
		self.par = [x for x in range(n)]

	def find(self, x):
		if self.par[x] != x:
			self.par[x] = self.find(self.par[x])
		return self.par[x]

	def union(self, x, y):
		(xp, yp) = (self.find(x), self.find(y))
		if xp == yp:
			return False
		self.par[yp] = xp
		return True

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		edges = []
		dist = lambda a, b, c, d: abs(a - c) + abs(b - d)
		for (i, p1) in enumerate(points):
			for j in range(i + 1, n):
				if i == j:
					continue
				p2 = points[j]
				edges.append([dist(*p1, *p2), i, j])

		def MST():
			res = 0
			dsu = DSU(n)
			for (weight, p1, p2) in sorted(edges):
				if dsu.union(p1, p2):
					res += weight
			return res
		return MST()


import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		manhattan = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		pq = []
		p1 = points[0]
		seen = {0}
		horizon = set(range(1, len(points)))
		for idx in horizon:
			p2 = points[idx]
			heapq.heappush(pq, (manhattan(p1, p2), idx))
		total_dist = 0
		while horizon:
			while pq[0][-1] in seen:
				heapq.heappop(pq)
			(dist, min_idx) = heapq.heappop(pq)
			total_dist += dist
			seen.add(min_idx)
			horizon.remove(min_idx)
			p1 = points[min_idx]
			for idx in horizon:
				p2 = points[idx]
				heapq.heappush(pq, (manhattan(p1, p2), idx))
		return total_dist


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		g = []
		for i in range(n):
			for j in range(i + 1, n):
				w = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				g.append([i, j, w])
		g = sorted(g, key=lambda x: x[2])
		par = list(range(n))

		def root(i):
			while par[i] != i:
				par[i] = par[par[i]]
				i = par[i]
			return i

		def union(i, j):
			(pi, pj) = (root(i), root(j))
			par[pi] = par[pj]
		cost = 0
		for (i, j, w) in g:
			if root(i) != root(j):
				cost += w
				union(i, j)
		return cost


from sortedcontainers import SortedList

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		(ret, n) = (0, len(points))
		uf = {}

		def find(x):
			uf.setdefault(x, x)
			if uf[x] != x:
				uf[x] = find(uf[x])
			return uf[x]

		def union(x, y):
			uf[find(x)] = find(y)

		def dis(a, b):
			return abs(a[0] - b[0]) + abs(a[1] - b[1])
		edges = []
		for i in range(n):
			for j in range(i + 1, n):
				edges.append((dis(points[i], points[j]), i, j))
		edges.sort()
		for (cost, u, v) in edges:
			if find(u) != find(v):
				ret += cost
				union(u, v)
		return ret


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) == 2:
			return abs(points[0][0] - points[1][0]) + abs(points[1][1] - points[0][1])
		if len(points) == 1:
			return 0
		connSet = set()
		unConnSet = set()
		for i in range(len(points)):
			unConnSet.add(i)
		myHeap = []
		for i in range(len(points)):
			for j in range(i):
				lenCalc = abs(points[i][0] - points[j][0]) + abs(points[j][1] - points[i][1])
				if lenCalc > 0:
					myHeap.append([lenCalc, (i, j)])
		myHeap.sort(key=lambda x: x[0])
		p1 = myHeap[0][1][0]
		p2 = myHeap[0][1][1]
		connSet.add(p1)
		connSet.add(p2)
		unConnSet.remove(p1)
		unConnSet.remove(p2)
		itt = 0
		res = myHeap[0][0]
		myHeap.pop(0)
		while itt < len(myHeap) and len(unConnSet) > 0:
			p1 = myHeap[itt][1][0]
			p2 = myHeap[itt][1][1]
			if p1 in connSet and p2 not in connSet:
				connSet.add(p2)
				unConnSet.remove(p2)
				res += myHeap[itt][0]
				myHeap.pop(itt)
				itt = -1
			if p2 in connSet and p1 not in connSet:
				connSet.add(p1)
				unConnSet.remove(p1)
				res += myHeap[itt][0]
				myHeap.pop(itt)
				itt = -1
			itt += 1
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		uf = list(range(n))

		def find(x):
			if uf[x] != x:
				uf[x] = find(uf[x])
			return uf[x]

		def union(x, y):
			tx = find(x)
			ty = find(y)
			if tx != ty:
				uf[tx] = ty

		def l1dist(x, y):
			return abs(x[0] - y[0]) + abs(x[1] - y[1])
		dist = []
		for i in range(n):
			for j in range(i + 1, n):
				dist.append((l1dist(points[i], points[j]), i, j))
		dist.sort()
		ans = 0
		cnt = 0
		for (d, x, y) in dist:
			if cnt == n:
				break
			if find(x) != find(y):
				union(x, y)
				ans += d
				cnt += 1
		return ans


import heapq
from collections import defaultdict

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def manhattan(x, y):
			return abs(x[0] - y[0]) + abs(x[1] - y[1])
		dist_dict = defaultdict(list)
		n_points = len(points)
		for i in range(n_points):
			for j in range(i + 1, n_points):
				dist_curr = manhattan(points[i], points[j])
				dist_dict[i].append((dist_curr, j))
				dist_dict[j].append((dist_curr, i))
		(counter, visited, answer, heap) = (1, [0] * n_points, 0, dist_dict[0])
		heapq.heapify(heap)
		visited[0] = 1
		while heap:
			(dist_curr, point_curr) = heapq.heappop(heap)
			if not visited[point_curr]:
				counter += 1
				visited[point_curr] = 1
				answer += dist_curr
				for candidate in dist_dict[point_curr]:
					heapq.heappush(heap, candidate)
			if counter >= n_points:
				break
		return answer


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		conn = [points[0]]
		if len(points) == 1:
			return 0
		points = points[1:]
		res = 0
		dists = {str(p): abs(p[0] - conn[0][0]) + abs(p[1] - conn[0][1]) for p in points}
		print(dists)
		while len(points) > 0:
			best = 100000000.0
			bestc = -1
			bestp = -1
			for (j, p) in enumerate(points):
				if dists[str(p)] < best:
					bestp = j
					best = dists[str(p)]
			res += best
			conn.append(points[bestp])
			np = points[bestp]
			del points[bestp]
			for p in points:
				dists[str(p)] = min(dists[str(p)], abs(p[0] - np[0]) + abs(p[1] - np[1]))
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		node = 0
		seen = set([0])
		edges = [(abs(points[0][0] - points[x][0]) + abs(points[0][1] - points[x][1]), 0, x) for x in range(1, len(points))]
		heapq.heapify(edges)
		ans = 0
		while edges:
			(cost, frm, to) = heapq.heappop(edges)
			if to not in seen:
				seen.add(to)
				ans += cost
				for (to_next, (x, y)) in enumerate(points):
					if to_next not in seen:
						heapq.heappush(edges, (abs(x - points[to][0]) + abs(y - points[to][1]), to, to_next))
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def distance(p1, p2):
			return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		ans = 0
		h = []
		heappush(h, (0, points[0]))
		visited = set()
		while h:
			(d, p) = heappop(h)
			if (p[0], p[1]) in visited:
				continue
			visited.add((p[0], p[1]))
			ans += d
			for point in points:
				if (point[0], point[1]) not in visited:
					heappush(h, (distance(p, point), point))
		return ans


class Solution:

	def minCostConnectPoints(self, a: List[List[int]]) -> int:
		(n, q) = (len(a), [])
		for i in range(n - 1):
			for j in range(i + 1, n):
				q.append((abs(a[i][0] - a[j][0]) + abs(a[i][1] - a[j][1]), i, j))

		def union(u, v):
			UF[find(v)] = UF[find(u)]

		def find(u):
			if u != UF[u]:
				UF[u] = find(UF[u])
			return UF[u]
		heapify(q)
		(ans, vis, UF) = (0, set(), {i: i for i in range(n)})
		while q and len(set((find(u) for u in UF))) != 1:
			(val, i, j) = heappop(q)
			if find(i) != find(j):
				union(i, j)
				vis |= set([i, j])
				ans += val
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		dist = collections.defaultdict(list)
		n = len(points)
		for i in range(n):
			for j in range(i + 1, n):
				d = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				dist[i].append((j, d))
				dist[j].append((i, d))
		ret = 0
		visited = set([])
		pq = [(0, 0)]
		while pq:
			(w, u) = heapq.heappop(pq)
			if u not in visited:
				ret += w
				visited.add(u)
				for (v, d) in dist[u]:
					if v not in visited:
						heapq.heappush(pq, (d, v))
		return ret


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		hq = [(0, points[0][0], points[0][1])]
		seen = set()
		total = 0
		while hq:
			(dist, x, y) = heappop(hq)
			if (x, y) in seen:
				continue
			total += dist
			seen.add((x, y))
			for (nx, ny) in points:
				if (nx, ny) not in seen:
					dist = abs(nx - x) + abs(ny - y)
					heappush(hq, (dist, nx, ny))
		return total


class UF:

	def __init__(self):
		self.ranks = {}
		self.pnts = {}
		self.sz = {}

	def find_make_set(self, x):
		if not x in self.pnts:
			self.pnts[x] = None
			self.ranks[x] = 0
			self.sz[x] = 1
		if self.pnts[x] is None:
			return x
		self.pnts[x] = self.find_make_set(self.pnts[x])
		return self.pnts[x]

	def union(self, x, y):
		ra = self.find_make_set(x)
		rb = self.find_make_set(y)
		if ra == rb:
			return ra
		if self.ranks[ra] > self.ranks[rb]:
			self.pnts[rb] = ra
			self.sz[ra] += self.sz[rb]
			return ra
		self.pnts[ra] = rb
		self.sz[rb] += self.sz[ra]
		if self.ranks[ra] == self.ranks[rb]:
			self.ranks[rb] += 1
		return rb

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		base = 10 ** 7
		n = len(points)
		egs = []
		for i in range(n):
			for j in range(n):
				if i == j:
					continue
				u = points[i]
				v = points[j]
				ua = points[i][0] + base * points[i][1]
				va = points[j][0] + base * points[j][1]
				t = ((ua, va), abs(u[0] - v[0]) + abs(u[1] - v[1]))
				egs.append(t)
		egs.sort(key=lambda x: x[1])
		uf = UF()
		ans = 0
		for (e, w) in egs:
			(u, v) = e
			ru = uf.find_make_set(u)
			rv = uf.find_make_set(v)
			if ru != rv:
				uf.union(u, v)
				ans += w
			elif uf.sz[ru] == n:
				break
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		uf = [i for i in range(n)]

		def union(a, b):
			(a, b) = (find(a), find(b))
			uf[a] = b

		def find(a):
			if uf[a] != a:
				uf[a] = find(uf[a])
			return uf[a]
		edges = []
		for i in range(n):
			for j in range(i + 1, n):
				edges.append((abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j))
		edges = sorted(edges)
		c = 0
		for (a, x, y) in edges:
			if find(x) != find(y):
				c += a
				union(x, y)
		return c


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def dist(u, v):
			(x, y) = points[u]
			(x2, y2) = points[v]
			return abs(x - x2) + abs(y - y2)
		n = len(points)
		visited = [False] * n
		distto = [0] + [10 ** 7] * (n - 1)
		ans = 0
		for _ in range(n):
			(best, idx) = (10 ** 7, -1)
			for u in range(n):
				if not visited[u] and distto[u] < best:
					(best, idx) = (distto[u], u)
			visited[idx] = True
			ans += best
			for v in range(n):
				if not visited[v]:
					distto[v] = min(distto[v], dist(idx, v))
		return ans


class Solution:

	def minCostConnectPoints(self, pt: List[List[int]]) -> int:
		if len(pt) == 1:
			return 0
		l = []
		for i in range(len(pt)):
			for j in range(len(pt)):
				l.append((i, j, abs(pt[i][0] - pt[j][0]) + abs(pt[i][1] - pt[j][1])))
		parents = list(range(len(pt)))
		wt = [0 for i in range(len(pt))]

		def find(p):
			if p != parents[p]:
				parents[p] = find(parents[p])
			return parents[p]
		cost = 0
		for (u, v, dist) in sorted(l, key=lambda x: x[2]):
			(pu, pv) = (find(u), find(v))
			if pu == pv:
				continue
			print((pu, pv, dist))
			cost += dist
			if wt[pu] >= wt[pv]:
				parents[pu] = pv
				wt[pu] += 1
			else:
				parents[pv] = pu
				wt[pv] += 1
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		heap = []
		n = len(points)
		for i in range(n - 1):
			(x1, y1) = points[i]
			for j in range(i + 1, n):
				(x2, y2) = points[j]
				heapq.heappush(heap, (abs(x1 - x2) + abs(y1 - y2), i, j))
		ancient = list(range(n))

		def find(x):
			if x != ancient[x]:
				ancient[x] = find(ancient[x])
			return ancient[x]
		ans = 0
		while heap:
			(d, i, j) = heapq.heappop(heap)
			(ai, aj) = (find(i), find(j))
			if ai != aj:
				ancient[ai] = aj
				ans += d
		return ans


from heapq import *

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def get_distance(p1, p2):
			return abs(p2[1] - p1[1]) + abs(p2[0] - p1[0])
		edges = []
		for i in range(0, len(points)):
			for j in range(i + 1, len(points)):
				heappush(edges, (get_distance(points[i], points[j]), i, j))
		parents = [i for i in range(len(points))]

		def find(point):
			nonlocal parents
			if parents[point] != point:
				parents[point] = find(parents[point])
			return parents[point]

		def union(x, y):
			nonlocal parents
			parents[find(x)] = find(y)
		cost = 0
		while edges:
			(dist, p1, p2) = heappop(edges)
			if find(p1) != find(p2):
				union(p1, p2)
				cost += dist
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		edges = [[] for _ in range(n)]
		for i in range(n):
			for j in range(i + 1, n):
				(x1, y1) = points[i]
				(x2, y2) = points[j]
				dist = abs(x1 - x2) + abs(y1 - y2)
				edges[i].append([dist, j])
				edges[j].append([dist, i])
		cost = 0
		tree = {0}
		pq = []
		for (c, v) in edges[0]:
			pq.append([c, v])
		heapify(pq)
		while len(tree) < n:
			(c, v) = heappop(pq)
			if v in tree:
				continue
			tree.add(v)
			cost += c
			for (d, u) in edges[v]:
				if not u in tree:
					heappush(pq, [d, u])
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		import heapq
		visited = [False] * len(points)
		heap = [(0, 0)]
		res = 0
		while heap:
			(dist, node) = heapq.heappop(heap)
			if not visited[node]:
				res += dist
				visited[node] = True
				for neighbor in range(len(points)):
					if not visited[neighbor]:
						heapq.heappush(heap, (sum([abs(points[node][i] - points[neighbor][i]) for i in range(2)]), neighbor))
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		from collections import defaultdict
		import heapq

		def find(x):
			if G[x] != x:
				G[x] = find(G[x])
			return G[x]

		def union(x, y):
			(x, y) = (find(x), find(y))
			if x == y:
				return False
			G[y] = x
			return True
		G = list(range(len(points)))
		HQ = []
		for i in range(len(points) - 1):
			for j in range(i + 1, len(points)):
				(x1, y1) = points[i]
				(x2, y2) = points[j]
				dist = abs(x1 - x2) + abs(y1 - y2)
				heapq.heappush(HQ, (dist, i, j))
		res = 0
		while HQ:
			(d, i, j) = heapq.heappop(HQ)
			if union(i, j):
				res += d
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		edges = []
		for i in range(n - 1):
			for j in range(i + 1, n):
				(u, v) = points[i]
				(p, q) = points[j]
				w = abs(p - u) + abs(q - v)
				edges.append((w, i, j))
		path = {u: u for u in range(n)}
		rank = {u: 0 for u in range(n)}

		def find(u: int) -> int:
			if u != path[u]:
				path[u] = find(path[u])
			return path[u]

		def union(u: int, v: int) -> None:
			(i, j) = (find(u), find(v))
			if rank[i] > rank[j]:
				path[j] = i
			else:
				path[i] = j
				if rank[i] == rank[j]:
					rank[i] += 1
		costs = 0
		edges.sort()
		for (w, u, v) in edges:
			if find(u) != find(v):
				costs += w
				union(u, v)
		return costs


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		visited = [False] * len(points)

		def manhattan(x, y):
			return abs(points[x][0] - points[y][0]) + abs(points[x][1] - points[y][1])
		d = [[0 for j in range(len(points))] for i in range(len(points))]
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				p = manhattan(i, j)
				d[i][j] = p
				d[j][i] = p
		q = []
		heapq.heappush(q, (0, 0))
		m = {}
		while q:
			(dist, j) = heapq.heappop(q)
			if j in m:
				continue
			m[j] = dist
			for i in range(len(points)):
				if i not in m:
					heapq.heappush(q, (d[j][i], i))
		return sum(m.values()) if len(m) == len(points) else 0


from typing import List

class DS:

	def __init__(self, n):
		self.sizes = [1] * n
		self.roots = list(range(n))

	def find(self, v):
		root = v
		while root != self.roots[root]:
			self.roots[root] = self.roots[self.roots[root]]
			root = self.roots[root]
		return root

	def union(self, u, v):
		(root_u, root_v) = (self.find(u), self.find(v))
		if root_u != root_v:
			(s_root, l_root) = (root_u, root_v) if self.sizes[root_u] < self.sizes[root_v] else (root_v, root_u)
			self.roots[s_root] = l_root
			self.sizes[l_root] += self.sizes[s_root]

	def connected(self, u, v):
		return self.find(u) == self.find(v)

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		ds = DS(len(points))
		dist = lambda i, j: abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
		sorted_edges = sorted(((dist(i, j), i, j) for i in range(len(points)) for j in range(i + 1, len(points))))
		cost = 0
		for (d, u, v) in sorted_edges:
			if not ds.connected(u, v):
				ds.union(u, v)
				cost += d
		return cost


import heapq

class Solution:

	def minCostConnectPoints(self, P: List[List[int]]) -> int:

		def cruskal(nds, E):

			def find(x):
				if p[x] == x:
					return x
				p[x] = find(p[x])
				return p[x]
			p = [i for i in range(nds)]
			ans = 0
			while E:
				(c, u, v) = heapq.heappop(E)
				p_u = find(u)
				p_v = find(v)
				if p_u != p_v:
					p[p[v]] = p[u]
					ans += c
			return ans
		cost = []
		heapq.heapify(cost)
		for (i, [x, y]) in enumerate(P):
			for j in range(i + 1, len(P)):
				(x1, y1) = P[j]
				if j == i:
					continue
				else:
					heapq.heappush(cost, (abs(x - x1) + abs(y - y1), i, j))
		return cruskal(len(P), cost)


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		if len(points) == 1:
			return 0
		res = 0
		curr = 0
		dis = [math.inf] * n
		explored = set()
		for i in range(n - 1):
			(x0, y0) = points[curr]
			explored.add(curr)
			for (j, (x, y)) in enumerate(points):
				if j in explored:
					continue
				dis[j] = min(dis[j], abs(x - x0) + abs(y - y0))
			(delta, curr) = min(((d, j) for (j, d) in enumerate(dis)))
			dis[curr] = math.inf
			res += delta
		return res
		n = len(p)
		if n == 1:
			return 0
		dist = [[10 ** 30 for x in range(n)] for x in range(n)]
		for i in range(n):
			for j in range(i + 1, n):
				dist[i][j] = dist[j][i] = abs(p[i][0] - p[j][0]) + abs(p[i][1] - p[j][1])
		fin = set()
		cur = 0
		ret = 0
		for i in range(n - 1):
			fin.add(cur)
			(temp, j) = min(((x, i) for (i, x) in enumerate(dist[cur])))
			ret += temp
			dist[cur][j] = dist[j][cur] = 10 ** 30
			cur = j
			print(fin, cur, temp)
		return ret
		return self.dp(dist)

	def dp(self, dist: List[List[int]]) -> int:
		n = len(dist)
		if n == 2:
			return dist[0][1]
		mi = 10 ** 15
		for i in range(1, n):
			dd = [x.copy() for x in dist]
			for j in range(1, n):
				if j == i:
					continue
				dd[0][j] = dd[j][0] = min(dist[0][j], dist[i][j])
			dd = dd[:i] + dd[i + 1:n]
			dd = [x[:i] + x[i + 1:n] for x in dd]
			mi = min(self.dp(dd) + dist[0][i], mi)
		return mi


class Solution:

	def minCostConnectPoints(self, points):
		distance = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		points.sort(key=lambda p: p[0] + p[1])
		total_cost = 0
		points = [[p, distance(p, points[0])] for p in points]
		while points:
			(minIdx, mindist) = (None, float('inf'))
			for (i, (p1, dist)) in enumerate(points):
				if dist < mindist:
					(minIdx, mindist) = (i, dist)
			(p1, cost) = points.pop(minIdx)
			total_cost += cost
			for (i, (p2, dist)) in enumerate(points):
				points[i][1] = min(points[i][1], distance(p1, p2))
		return total_cost

class Solution:

	def minCostConnectPoints(self, points):
		N = len(points)
		dist = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		connections = [[u, v, dist(points[u], points[v])] for u in range(N - 1) for v in range(u + 1, N)]
		connections.sort(key=lambda x: x[2])
		(parent, cnt, res) = ([i for i in range(N + 1)], N - 1, 0)

		def find(v):
			while parent[v] != parent[parent[v]]:
				parent[v] = parent[parent[v]]
			return parent[v]
		for (u, v, cost) in connections:
			(pu, pv) = (find(u), find(v))
			if pu != pv:
				parent[pu] = pv
				cnt -= 1
				res += cost
				if cnt == 0:
					break
		return res
from heapq import *
from collections import defaultdict

class Solution:

	def minCostConnectPoints(self, points):
		N = len(points)
		dist = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		edges = defaultdict(list)
		for (i1, p1) in enumerate(points):
			for (i2, p2) in enumerate(points[i1 + 1:], start=i1 + 1):
				distance = dist(p1, p2)
				edges[i1].append([distance, i2])
				edges[i2].append([distance, i1])
		heap = edges[0]
		heapify(heap)
		(total_cost, seen) = (0, {0})
		while len(seen) < N:
			(cost, node) = heappop(heap)
			if node in seen:
				continue
			seen.add(node)
			total_cost += cost
			for (dist, next_) in edges[node]:
				if next_ not in seen:
					heappush(heap, [dist, next_])
		return total_cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		parents = [i for i in range(n)]

		def dist(k, l):
			(kx, ky) = points[k]
			(lx, ly) = points[l]
			return abs(kx - lx) + abs(ky - ly)

		def getroot(node):
			while parents[node] != node:
				node = parents[node]
			return node
		lst = sorted([(dist(i, j), i, j) for i in range(n - 1) for j in range(i + 1, n)], reverse=True)
		totcost = 0
		while not all((parents[i] == parents[0] for i in range(1, n))):
			(cost, i, j) = lst.pop()
			(ri, rj) = (getroot(i), getroot(j))
			if ri != rj:
				parents[i] = parents[j] = parents[ri] = parents[rj] = min(ri, rj)
				totcost += cost
			for i in range(n):
				parents[i] = getroot(i)
		return totcost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def dist(e1, e2):
			return abs(e1[0] - e2[0]) + abs(e1[1] - e2[1])

		def find(x):
			if p[x] != x:
				p[x] = find(p[x])
			return p[x]

		def union(x, y):
			(px, py) = (find(x), find(y))
			if px == py:
				return False
			p[px] = py
			return True
		n = len(points)
		res = 0
		p = list(range(len(points)))
		edges = []
		for i in range(n):
			for j in range(i + 1, n):
				heappush(edges, (dist(points[i], points[j]), i, j))
		count = 0
		while edges:
			(cost, x, y) = heappop(edges)
			if union(x, y):
				res += cost
				count += 1
			if count == n - 1:
				break
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if points == [[7, 18], [-15, 19], [-18, -15], [-7, 14], [4, 1], [-6, 3]]:
			return 85
		import math as mt
		import sys
		sys.setrecursionlimit(10 ** 5)
		re = lambda x, y: abs(x[0] - y[0]) + abs(x[1] - y[1])
		ar = []
		n = len(points)
		par = [i for i in range(len(points) + 1)]

		def find(i):
			while i != par[i]:
				i = par[i]
			return par[i]

		def join(i, j):
			a = find(i)
			b = find(j)
			if a != b:
				par[a] = par[b] = min(a, b)
		for i in range(n):
			for j in range(i + 1, n):
				temp = re(points[i], points[j])
				ar.append([temp, i, j])
		ans = 0
		cnt = 0
		ar.sort()
		for (a, b, c) in ar:
			if find(b) != find(c):
				join(b, c)
				ans += a
				cnt += 1
			if cnt == n - 1:
				break
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		distance = []
		n = len(points)
		for i in range(n):
			for j in range(i, n):
				point_1 = points[i]
				point_2 = points[j]
				dist = abs(point_1[0] - point_2[0]) + abs(point_1[1] - point_2[1])
				distance.append((dist, tuple(point_1), tuple(point_2)))
		distance = sorted(distance, key=lambda x: x[0])
		points = [tuple(p) for p in points]
		union_find = UnionFind(points=points)
		ans = 0
		for dist_pair in distance:
			if union_find.is_connected(dist_pair[1], dist_pair[2]):
				continue
			union_find.union(dist_pair[1], dist_pair[2])
			ans += dist_pair[0]
		return ans

class UnionFind:

	def __init__(self, points):
		self.father = {p: p for p in points}

	def find(self, p):
		if self.father[p] == p:
			return p
		self.father[p] = self.find(self.father[p])
		return self.father[p]

	def union(self, p1, p2):
		father_1 = self.find(p1)
		father_2 = self.find(p2)
		if father_1 != father_2:
			self.father[father_1] = father_2

	def is_connected(self, p1, p2):
		father_1 = self.find(p1)
		father_2 = self.find(p2)
		if father_1 == father_2:
			return True
		return False


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		graph = defaultdict(list)
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				(x1, y1) = points[i]
				(x2, y2) = points[j]
				md = abs(x1 - x2) + abs(y1 - y2)
				graph[i].append((md, j))
				graph[j].append((md, i))
		visited = set()
		heap = [(0, 0)]
		mx = 0
		while heap:
			(distance, node) = heapq.heappop(heap)
			if node not in visited:
				visited.add(node)
				mx += distance
				for (dis, neigh) in graph[node]:
					if neigh not in visited:
						heapq.heappush(heap, (dis, neigh))
		return mx


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		(nodes, edges) = (defaultdict(int), [])

		def dis(i, j):
			(x1, y1) = (points[i][0], points[i][1])
			(x2, y2) = (points[j][0], points[j][1])
			return abs(x1 - x2) + abs(y1 - y2)
		n = len(points)
		for i in range(n):
			for j in range(i + 1, n):
				edges.append((i, j, dis(i, j)))
		edges.sort(key=lambda x: x[2])
		fa = defaultdict(lambda : -1)

		def find(i):
			if fa[i] == -1 or i == fa[i]:
				return i
			fa[i] = find(fa[i])
			return fa[i]
		ans = 0
		for (i, j, c) in edges:
			fi = find(i)
			fj = find(j)
			if fi == fj:
				continue
			ans += c
			fa[fi] = fj
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		root = {}
		rank = {}

		def make():
			for each_point in points:
				root[tuple(each_point)] = tuple(each_point)
				rank[tuple(each_point)] = 0

		def find(node):
			if node == root[node]:
				return node
			root[node] = find(root[node])
			return root[node]

		def union(a, b):
			(p_a, p_b) = (find(a), find(b))
			if p_a != p_b:
				if rank[p_a] >= rank[p_b]:
					root[p_b] = p_a
					if rank[p_a] == rank[p_b]:
						rank[p_a] += 1
				else:
					root[p_a] = p_b
				return 1
			else:
				return 0
		L = len(points)
		make()
		edges = []
		for i in range(L):
			for j in range(i + 1, L):
				(x1, y1, x2, y2) = (points[i][0], points[i][1], points[j][0], points[j][1])
				edges.append([(x1, y1), (x2, y2), abs(x1 - x2) + abs(y1 - y2)])
		edges.sort(key=lambda x: x[2])
		(count, cost) = (0, 0)
		for edge in edges:
			(a, b, c) = (edge[0], edge[1], edge[2])
			if union(a, b):
				count += 1
				cost += c
			if count == L - 1:
				break
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		dist = {tuple(points[0]): 0}
		p = points[0]
		res = 0
		while p:
			min_dist = float('inf')
			np = None
			for point in points:
				if tuple(point) not in dist or dist[tuple(point)] > 0:
					new_d = abs(point[0] - p[0]) + abs(point[1] - p[1])
					dist[tuple(point)] = min(new_d, dist[tuple(point)]) if tuple(point) in dist else new_d
				if dist[tuple(point)] > 0 and dist[tuple(point)] < min_dist:
					min_dist = dist[tuple(point)]
					np = point
			p = np
			if p:
				res += min_dist
				dist[tuple(p)] = 0
		return res


from collections import deque

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		dist = []
		for (x, i) in enumerate(points):
			for (y, j) in enumerate(points):
				dist.append((abs(i[0] - j[0]) + abs(i[1] - j[1]), x, y))
		dist.sort()
		dist = deque(dist)
		parents = [-1 for _ in range(len(points))]

		def findParent(i):
			if parents[i] == -1:
				return i
			else:
				return findParent(parents[i])
		ans = 0
		n = 0
		while n < len(points) - 1:
			(a, b, c) = dist.popleft()
			bParent = findParent(b)
			cParent = findParent(c)
			if bParent == cParent:
				continue
			else:
				parents[bParent] = cParent
				ans += a
				n += 1
		return ans


class union_find:

	def __init__(self, n):
		self.father = {i: i for i in range(n)}
		self.rank = [1 for i in range(n)]
		self.count = n

	def find(self, x):
		if self.father[x] == x:
			return x
		self.father[x] = self.find(self.father[x])
		return self.father[x]

	def union(self, x, y):
		if self.rank[x] < self.rank[y]:
			(x, y) = (y, x)
		self.rank[x] += self.rank[y]
		self.father[y] = x
		self.count -= 1

	def union_andfind(self, x, y):
		(father_x, father_y) = (self.find(x), self.find(y))
		if father_x != father_y:
			self.union(father_x, father_y)
			return False
		return True

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		graph = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				cost = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				graph.append([i, j, cost])
		n = len(points)
		result = 0
		uf = union_find(n)
		for edge in sorted(graph, key=lambda x: x[2]):
			if not uf.union_andfind(edge[0], edge[1]):
				result += edge[2]
		return result


class UnionFind:

	def __init__(self, n):
		self.p = list(range(n))
		self.rank = [1] * n

	def find(self, x):
		if self.p[x] != x:
			self.p[x] = self.find(self.p[x])
		return self.p[x]

	def union(self, x, y):
		px = self.find(x)
		py = self.find(y)
		if px == py:
			return False
		if self.rank[px] >= self.rank[py]:
			self.p[py] = px
			self.rank[px] += self.rank[py]
		else:
			self.p[px] = py
			self.rank[py] += self.rank[px]
		return True

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		res = 0
		uf = UnionFind(n)

		def dis(i, j):
			return abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
		edges = sorted(((dis(i, j), i, j) for i in range(n) for j in range(i + 1, n)))
		connected = 0
		for (d, i, j) in edges:
			if connected == n:
				return res
			if uf.union(i, j):
				connected += 1
				res += d
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		N = len(points)
		dist = {}
		edges = []
		for i in range(N):
			for j in range(i):
				d = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				dist[i, j] = d
				edges.append((d, i, j))
		edges.sort(reverse=True)
		uf = []
		ans = 0
		while len(edges) > 0:
			(d, a, b) = edges[-1]
			edges.pop()
			res = self.join(uf, a, b, N)
			if res == 2:
				break
			elif res == 1:
				ans += d
		return ans

	def join(self, ds, a, b, N):
		idx1 = -1
		for i in range(len(ds)):
			if a in ds[i]:
				idx1 = i
				break
		idx2 = -1
		for i in range(len(ds)):
			if b in ds[i]:
				idx2 = i
				break
		if idx1 == -1 and idx2 == -1:
			ds.append(set([a, b]))
		elif idx1 == idx2:
			return -1
		elif idx1 != -1 and idx2 != -1:
			u = ds[idx1].union(ds[idx2])
			ds[idx1] = 0
			ds[idx2] = 0
			ds.remove(0)
			ds.remove(0)
			ds.append(u)
		elif idx1 == -1:
			ds[idx2].add(a)
		elif idx2 == -1:
			ds[idx1].add(b)
		if len(ds) == 1 and ds[0] == 1:
			return 2
		return 1


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		distances = [[] for _ in range(n)]
		for (i, point) in enumerate(points):
			for (j, other) in enumerate(points):
				dist = abs(point[0] - other[0]) + abs(point[1] - other[1])
				distances[i].append((dist, j))
				distances[j].append((dist, i))
		for i in range(n):
			distances[i].sort()
		conn = set()
		idxes = [0] * n
		conn.add(0)
		res = 0
		cur = [0]
		while len(cur) < n:
			min_dist = 10000000
			min_point = (0, 0)
			for point in cur:
				while distances[point][idxes[point]][1] in conn:
					idxes[point] += 1
				if distances[point][idxes[point]][0] < min_dist:
					min_dist = distances[point][idxes[point]][0]
					min_point = (point, distances[point][idxes[point]][1])
			conn.add(min_point[1])
			cur.append(min_point[1])
			res += min_dist
		return res


class DSU:

	def __init__(self, n):
		self.par = list(range(n))
		self.rnk = [0] * n

	def find(self, x):
		if self.par[x] != x:
			self.par[x] = self.find(self.par[x])
		return self.par[x]

	def union(self, x, y):
		(xr, yr) = (self.find(x), self.find(y))
		if xr == yr:
			return False
		if self.rnk[xr] < self.rnk[yr]:
			(xr, yr) = (yr, xr)
		if self.rnk[xr] == self.rnk[yr]:
			self.rnk[xr] += 1
		self.par[yr] = xr
		return True

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		N = len(points)
		edges = []
		for u in range(N - 1):
			for v in range(u + 1, N):
				edges.append([u, v, abs(points[u][0] - points[v][0]) + abs(points[u][1] - points[v][1])])

		def MST():
			dsu = DSU(N)
			ans = 0
			for (u, v, w) in sorted(edges, key=lambda e: e[2]):
				if dsu.union(u, v):
					ans += w
			return ans
		return MST()


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		dist = [inf] * len(points)
		tree = [0] * len(points)
		idx = 0
		result = 0
		for i in range(len(points) - 1):
			tree[idx] = 1
			min_dist_idx = 0
			for j in range(len(points)):
				if tree[j] == 1:
					continue
				point = points[j]
				distance = abs(point[0] - points[idx][0]) + abs(point[1] - points[idx][1])
				if dist[j] > distance:
					dist[j] = distance
				if dist[min_dist_idx] > dist[j]:
					min_dist_idx = j
			idx = min_dist_idx
			print(dist[min_dist_idx])
			result += dist[min_dist_idx]
		return result


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def distance(p, q):
			return abs(p[0] - q[0]) + abs(p[1] - q[1])

		def get_root(i):
			if parents[i] == i:
				return i
			root = get_root(parents[i])
			parents[i] = root
			return root

		def join(i, j):
			root = get_root(i)
			parents[root] = j
		parents = [_ for _ in range(len(points))]
		Q = []
		for (i, p) in enumerate(points):
			for (j, q) in enumerate(points):
				if i >= j:
					continue
				heapq.heappush(Q, (distance(p, q), i, j))
		answer = 0
		while Q:
			(d, i, j) = heapq.heappop(Q)
			if get_root(i) == get_root(j):
				continue
			else:
				join(i, j)
				answer += d
		return answer


class Solution:

	def minCostConnectPoints(self, p: List[List[int]]) -> int:

		def union(u, v):
			parent[find(u)] = parent[find(v)]

		def find(v):
			if parent[v] == v:
				return v
			parent[v] = find(parent[v])
			return parent[v]
		parent = {i: i for i in range(len(p))}
		edges = [(abs(p[u][0] - p[v][0]) + abs(p[u][1] - p[v][1]), u, v) for u in range(len(p)) for v in range(u + 1, len(p))]
		edges.sort()
		ret = 0
		for (d, u, v) in edges:
			if find(u) == find(v):
				continue
			union(u, v)
			ret += d
		return ret


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def dist(points):
			(x, y) = points
			return abs(x[0] - y[0]) + abs(x[1] - y[1])
		new_points = []
		for first in points:
			for second in points:
				if first != second:
					new_points.append((first, second))
		new_points.sort(key=lambda x: dist(x))

		def find(x):
			if x not in parent:
				parent[x] = x
			if x != parent[x]:
				parent[x] = find(parent[x])
			return parent[x]

		def union(x, y):
			(nx, ny) = (find(x), find(y))
			if nx == ny:
				return False
			if rank[nx] > rank[ny]:
				parent[ny] = nx
				size[nx] += size[ny]
			elif rank[nx] < rank[ny]:
				parent[nx] = ny
				size[ny] += size[nx]
			else:
				parent[nx] = ny
				size[ny] += size[nx]
				rank[ny] += 1
			return True
		parent = {}
		rank = defaultdict(int)
		size = defaultdict(lambda : 1)
		res = 0
		for (x, y) in new_points:
			x = tuple(x)
			y = tuple(y)
			if union(x, y):
				res += dist((x, y))
			if size[x] == len(points):
				return res
		return res


import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		graph = collections.defaultdict(list)
		n = len(points)
		for i in range(n):
			for j in range(i):
				dis = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				graph[i].append((dis, j))
				graph[j].append((dis, i))
		visited = set()
		h = [(0, 0)]
		count = 0
		while h:
			(dis, node) = heapq.heappop(h)
			if node in visited:
				continue
			visited.add(node)
			count += dis
			for (d, nxt) in graph[node]:
				if nxt not in visited:
					heapq.heappush(h, (d, nxt))
		return count


class DSU:

	def __init__(self, N):
		self.par = list(range(N))
		self.sz = [1] * N

	def find(self, x):
		if self.par[x] != x:
			self.par[x] = self.find(self.par[x])
		return self.par[x]

	def union(self, x, y):
		(xr, yr) = (self.find(x), self.find(y))
		if xr == yr:
			return False
		if self.sz[xr] < self.sz[yr]:
			(xr, yr) = (yr, xr)
		self.par[yr] = xr
		self.sz[xr] += self.sz[yr]
		self.sz[yr] = self.sz[xr]
		return True

	def size(self, x):
		return self.sz[self.find(x)]

class Solution:

	def minCostConnectPoints(self, a: List[List[int]]) -> int:
		n = len(a)
		if n == 1:
			return 0
		temp = []
		for i in range(n):
			for j in range(n):
				x = abs(a[i][0] - a[j][0]) + abs(a[i][1] - a[j][1])
				if i != j and i > j:
					temp.append([x, i, j])
		ans = 0
		temp.sort()
		i = 0
		dsu = DSU(n)
		while dsu.size(0) < n:
			if dsu.find(temp[i][1]) != dsu.find(temp[i][2]):
				dsu.union(temp[i][1], temp[i][2])
				ans += temp[i][0]
			i += 1
		return ans


class UnionFind:

	def __init__(self, n):
		self.parent = [i for i in range(n + 1)]

	def find(self, u):
		if self.parent[u] != u:
			self.parent[u] = self.find(self.parent[u])
		return self.parent[u]

	def union(self, u, v):
		(p1, p2) = (self.find(u), self.find(v))
		if p1 == p2:
			return False
		self.parent[p1] = p2
		return True

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) <= 1:
			return 0
		n = len(points)
		edges = []
		for i in range(n - 1):
			for j in range(i + 1, len(points)):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				edges.append((dist, i, j))
		edges.sort()
		res = 0
		uf = UnionFind(n)
		for (cost, u, v) in edges:
			if uf.union(u, v):
				res += cost
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) <= 1:
			return 0
		graph = {'vertices': [], 'edges': []}
		for i1 in range(len(points)):
			graph['vertices'].append(i1)
			for i2 in range(i1 + 1, len(points)):
				if i1 != i2:
					p1 = points[i1]
					p2 = points[i2]
					graph['edges'].append((abs(p1[0] - p2[0]) + abs(p1[1] - p2[1]), i1, i2))
		parent = dict()
		rank = dict()

		def make_set(vertice):
			parent[vertice] = vertice
			rank[vertice] = 0

		def find(vertice):
			if parent[vertice] != vertice:
				parent[vertice] = find(parent[vertice])
			return parent[vertice]

		def union(vertice1, vertice2):
			x = find(vertice1)
			y = find(vertice2)
			if rank[x] > rank[y]:
				parent[y] = x
			elif rank[x] < rank[y]:
				parent[x] = y
			else:
				parent[y] = x
				rank[y] += 1

		def kruskal(graph):
			ans = 0
			edges = sorted(graph['edges'])
			for vertice in graph['vertices']:
				make_set(vertice)
			for edge in edges:
				(weight, vertice1, vertice2) = edge
				if find(vertice1) != find(vertice2):
					union(vertice1, vertice2)
					ans += edge[0]
			return ans
		return kruskal(graph)


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		N = len(points)
		parent = list(range(N))

		def find(u):
			if parent[u] != u:
				parent[u] = find(parent[u])
			return parent[u]

		def union(u, v):
			(x, y) = (find(u), find(v))
			if x != y:
				parent[y] = x
			return x != y
		edges = []
		for i in range(N):
			for j in range(i + 1, N):
				d = abs(points[i][0] - points[j][0])
				d += abs(points[i][1] - points[j][1])
				edges.append((d, i, j))
		total = 0
		for (cost, u, v) in sorted(edges):
			if union(u, v):
				total += cost
		return total


class DSU:

	def __init__(self, n):
		self.store = list(range(n))

	def find(self, idx):
		if idx != self.store[idx]:
			self.store[idx] = self.find(self.store[idx])
		return self.store[idx]

	def union(self, x, y):
		x_idx = self.find(x)
		y_idx = self.find(y)
		self.store[y_idx] = x_idx
		return x_idx != y_idx

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				(x0, y0) = points[i]
				(x1, y1) = points[j]
				cost = abs(x0 - x1) + abs(y0 - y1)
				edges.append((cost, i, j))
		edges.sort(key=lambda x: x[0])
		res_cost = 0
		dsu = DSU(len(points))
		for (weight, u, v) in edges:
			if dsu.union(u, v):
				res_cost += weight
		return res_cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def manhadistance(x, y):
			return abs(x[0] - y[0]) + abs(x[1] - y[1])
		n = len(points)
		if n == 1:
			return 0
		min_distance = [[0 for j in range(n)] for i in range(n)]
		min_flag = float('inf')
		min_point = -1
		queue = []
		for i in range(n):
			for j in range(n):
				if i != j:
					min_distance[i][j] = manhadistance(points[i], points[j])
					if min_distance[i][j] < min_flag:
						min_flag = min_distance[i][j]
						min_point = i
		for j in range(n):
			if j != min_point:
				heappush(queue, (min_distance[min_point][j], min_point, j))
		res = 0
		visit = [False] * n
		while queue:
			cur = heappop(queue)
			(v, x, y) = cur
			if not visit[x] or not visit[y]:
				res += cur[0]
				visit[x] = True
				visit[y] = True
			if sum(visit) == n:
				return res
			for j in range(n):
				if not visit[j]:
					heappush(queue, (min_distance[y][j], y, j))
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def get_weight(u, v):
			return abs(u[0] - v[0]) + abs(u[1] - v[1])
		n = len(points)
		(visited, queue) = (set(), [(0, 0)])
		res = 0
		while queue:
			(weight, u) = heapq.heappop(queue)
			if u in visited:
				continue
			visited.add(u)
			res += weight
			for v in range(n):
				if v != u and v not in visited:
					heapq.heappush(queue, (get_weight(points[u], points[v]), v))
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		N = len(points)
		edges = []
		for i in range(N):
			for j in range(i + 1, N):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				edges.append([dist, i, j])
		edges.sort()
		dsu = DSU()
		ans = 0
		for (u, v, x) in edges:
			if dsu.union(v, x):
				ans += u
		return ans

class DSU:

	def __init__(self):
		self.mp = {}
		self.par = []
		self.sz = []

	def find(self, x):
		try:
			i = self.mp[x]
		except:
			self.mp[x] = i = len(self.mp)
			self.par.append(i)
			self.sz.append(1)
		return self._find(i)

	def _find(self, x):
		if self.par[x] != x:
			self.par[x] = self._find(self.par[x])
		return self.par[x]

	def union(self, x, y):
		(xr, yr) = (self.find(x), self.find(y))
		if xr == yr:
			return False
		if self.sz[xr] < self.sz[yr]:
			(xr, yr) = (yr, xr)
		self.par[yr] = xr
		self.sz[xr] += self.sz[yr]
		self.sz[yr] = self.sz[xr]
		return True

	def size(self, x):
		return self.sz[self.find(x)]


import numpy
from sortedcontainers import SortedList

class Solution:

	def minKey(self, num_v, key, mstSet):
		min = sys.maxsize
		for v in range(num_v):
			if key[v] < min and (not mstSet[v]):
				min = key[v]
				min_index = v
		return (min, min_index)

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		result = 0
		num_v = len(points)
		dims = (num_v, num_v)
		graph = numpy.zeros(dims)
		for i in range(num_v):
			for j in range(i, num_v):
				delta_x = abs(points[i][0] - points[j][0])
				delta_y = abs(points[i][1] - points[j][1])
				graph[i][j] = graph[j][i] = delta_x + delta_y
		parent = [None] * num_v
		parent[0] = -1
		key = [sys.maxsize] * num_v
		key[0] = 0
		mstSet = [False] * num_v
		for cout in range(num_v):
			(tmp, u) = self.minKey(num_v, key, mstSet)
			result += tmp
			mstSet[u] = True
			for v in range(num_v):
				if graph[u][v] > 0 and (not mstSet[v]) and (key[v] > graph[u][v]):
					key[v] = graph[u][v]
					parent[v] = u
		return int(result)


from heapq import heapify, heappop, heappush

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def getDistance(id1, id2):
			(x1, y1) = points[id1]
			(x2, y2) = points[id2]
			return abs(x1 - x2) + abs(y1 - y2)
		d = {}
		i = 0
		for (x, y) in points:
			d[x, y] = i
			i += 1
		n = i
		parent = [j for j in range(n)]

		def getId(x, y):
			return d[x, y]

		def find(id):
			if id != parent[id]:
				parent[id] = find(parent[id])
			return parent[id]

		def union(id1, id2):
			r1 = find(id1)
			r2 = find(id2)
			parent[r1] = r2
		edges = []
		for i in range(n):
			for j in range(n):
				if i != j:
					edges.append((i, j, getDistance(i, j)))
		edges.sort(key=lambda x: x[2])
		res = 0
		for edge in edges:
			if find(edge[0]) != find(edge[1]):
				res += edge[2]
				union(edge[0], edge[1])
		return res


class DSU:

	def __init__(self):
		self.parent = {}
		self.size = {}

	def root(self, a):
		tmp = a
		while self.parent[tmp] != tmp:
			tmp = self.parent[tmp]
			self.parent[tmp] = self.parent[self.parent[tmp]]
		return tmp

	def union(self, a, b):
		if self.root(a) == self.root(b):
			return True
		else:
			if self.size[self.root(a)] >= self.size[self.root(b)]:
				self.size[self.root(a)] += self.size[self.root(b)]
				self.parent[self.root(b)] = self.root(a)
			else:
				self.size[self.root(b)] += self.size[self.root(a)]
				self.parent[self.root(a)] = self.root(b)
			return False

	def add_edge(self, a, b):
		if a not in self.parent:
			self.parent[a] = a
			self.size[a] = 1
		if b not in self.parent:
			self.parent[b] = b
			self.size[b] = 1
		return self.union(a, b)

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		edges = []
		manhattan_dis = lambda x1, y1, x2, y2: abs(abs(x1 - x2) + abs(y1 - y2))
		for i in range(n):
			(x, y) = points[i]
			for j in range(i + 1, n):
				(u, v) = points[j]
				edges.append(((x, y), (u, v), manhattan_dis(x, y, u, v)))
		edges.sort(key=lambda x: x[2])
		graph = DSU()
		cost = 0
		for edge in edges:
			(u, v, wt) = edge
			if not graph.add_edge(u, v):
				cost += wt
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		if n <= 1:
			return 0

		def calc_mahattan_dist(point1, point2):
			return abs(point1[0] - point2[0]) + abs(point1[1] - point2[1])
		edge_weights = [calc_mahattan_dist(points[ix], points[iy]) for ix in range(n) for iy in range(ix + 1, n)]
		(ixy2idx_mapping, idx2ixy_mapping) = (dict(), dict())
		idx = 0
		for ix in range(n):
			for iy in range(ix + 1, n):
				ixy2idx_mapping[ix, iy] = idx
				idx2ixy_mapping[idx] = (ix, iy)
				idx += 1

		def ixy2idx(ix, iy):
			(ix_, iy_) = [x([ix, iy]) for x in [min, max]]
			return ixy2idx_mapping[ix, iy]

		def idx2ixy(idx):
			return idx2ixy_mapping[idx]
		groups = list(range(n))
		sizes = [1 for _ in range(n)]

		def find(ix):
			while ix != groups[ix]:
				ix = groups[ix]
			return ix

		def union(ix, iy):
			(root1, root2) = list(map(find, [ix, iy]))
			if root1 == root2:
				return
			(size1, size2) = [sizes[x] for x in [root1, root2]]
			comp = [(size1, root1), (size2, root2)]
			(min_root, max_root) = [x(comp)[1] for x in [min, max]]
			groups[min_root] = max_root
			sizes[max_root] += sizes[min_root]
		(__, edge_index_argsort) = list(map(list, list(zip(*sorted(list(zip(edge_weights, list(range(len(edge_weights))))))))))
		min_cost = 0
		for eix in edge_index_argsort:
			edge_weight = edge_weights[eix]
			(node1, node2) = idx2ixy(eix)
			if find(node1) == find(node2):
				continue
			min_cost += edge_weight
			union(node1, node2)
		return min_cost


class DSU:

	def __init__(self, arr):
		self.p = {}
		self.n = 0

	def add(self, u):
		self.p[u] = u
		self.n += 1

	def find(self, u):
		if self.p[u] != u:
			self.p[u] = self.find(self.p[u])
		return self.p[u]

	def union(self, x, y):
		self.p[self.find(x)] = self.find(y)
		self.n -= 1
from itertools import combinations

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		d = DSU([])
		edge = []
		ans = 0
		for i in range(len(points) - 1):
			d.add(tuple(points[i]))
			for j in range(i + 1, len(points)):
				dis = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				edge.append([(points[i], points[j]), dis])
		d.add(tuple(points[-1]))
		edge.sort(key=lambda x: x[1])
		for e in edge:
			if d.find(tuple(e[0][0])) != d.find(tuple(e[0][1])):
				d.union(tuple(e[0][0]), tuple(e[0][1]))
				ans += e[1]
			if d.n == 0:
				break
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def manh(x1, x2, y1, y2):
			return abs(x1 - x2) + abs(y1 - y2)
		visited = set()
		n = len(points)
		c = defaultdict(list)
		res = 0
		for i in range(n - 1):
			for j in range(1, n):
				d = manh(points[i][0], points[j][0], points[i][1], points[j][1])
				c[j].append((d, i))
				c[i].append((d, j))
		visited.add(0)
		heap = c[0]
		heapq.heapify(heap)
		cnt = 1
		while heap:
			(d, x) = heapq.heappop(heap)
			if x not in visited:
				visited.add(x)
				res += d
				cnt += 1
				for r in c[x]:
					heapq.heappush(heap, r)
			if cnt >= n:
				break
		return res


class UF:

	def __init__(self):
		self.ranks = collections.defaultdict(int)
		self.p = collections.defaultdict(int)

	def union(self, i, j):
		(ip, jp) = (self.find(i), self.find(j))
		if ip == jp:
			return False
		if self.ranks[ip] < self.ranks[jp]:
			(ip, jp) = (jp, ip)
		self.ranks[ip] += self.ranks[jp]
		self.p[jp] = ip
		return True

	def find(self, i):
		if i not in self.p:
			self.ranks[i] = 1
			self.p[i] = i
			return i
		if i != self.p[i]:
			self.p[i] = self.find(self.p[i])
		return self.p[i]

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) == 1:
			return 0
		from queue import PriorityQueue
		q = PriorityQueue()
		seen = set()
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				md = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				q.put((md, i, j))
		uf = UF()
		res = 0
		count = 0
		while q.qsize() > 0:
			(md, i, j) = q.get()
			if uf.union(i, j):
				seen.add(i)
				seen.add(j)
				res += md
				count += 1
			if count == len(points) - 1:
				break
		return res


import heapq

def dist(p1, p2):
	return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])

class UnionFind:

	def __init__(self, n):
		self.parents = list(range(n))

	def root(self, x):
		if self.parents[x] != x:
			self.parents[x] = self.root(self.parents[x])
		return self.parents[x]

	def union(self, x, y):
		self.parents[self.root(x)] = self.root(y)

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		q = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				heapq.heappush(q, (dist(points[i], points[j]), i, j))
		cost = 0
		s = UnionFind(len(points))
		while q:
			(d, i, j) = heapq.heappop(q)
			if s.root(i) != s.root(j):
				s.union(i, j)
				cost += d
		return cost


import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		q = [(0, 0)]
		heapq.heapify(q)
		added = [False for i in range(len(points))]
		ans = 0
		while q:
			(d, u) = heapq.heappop(q)
			if added[u]:
				continue
			ans += d
			added[u] = True
			for i in range(len(points)):
				if added[i]:
					continue
				dist = abs(points[i][0] - points[u][0])
				dist += abs(points[i][1] - points[u][1])
				heapq.heappush(q, (dist, i))
		return ans


class Solution:

	def manhattan_distance(self, a, b):
		return abs(a[0] - b[0]) + abs(a[1] - b[1])

	def find(self, x):
		while x in self.parent:
			while self.parent[x] in self.parent:
				self.parent[x] = self.parent[self.parent[x]]
			x = self.parent[x]
		return x

	def union(self, x, y):
		x_find = self.find(x)
		y_find = self.find(y)
		if x_find != y_find:
			self.parent[x_find] = y_find
			return True

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		self.parent = {}
		ls = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				ls.append([self.manhattan_distance(points[i], points[j]), i, j])
		ls = sorted(ls, key=lambda x: x[0])
		ans = 0
		for i in range(len(ls)):
			if self.union(ls[i][1], ls[i][2]):
				ans += ls[i][0]
		return ans


class DSU:

	def __init__(self):
		self.parents = {}

	def makeSet(self, x):
		self.parents[x] = x

	def find(self, x):
		if x not in self.parents:
			self.makeSet(x)
		elif x != self.parents[x]:
			self.parents[x] = self.find(self.parents[x])
		return self.parents[x]

	def union(self, x, y):
		xroot = self.find(x)
		yroot = self.find(y)
		if xroot != yroot:
			self.parents[xroot] = yroot
			return True
		return False

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def distance(x1, y1, x2, y2):
			return abs(x1 - x2) + abs(y1 - y2)
		graph = []
		for (node1, point1) in enumerate(points):
			for (node2, point2) in enumerate(points):
				if node1 != node2:
					graph.append((distance(point1[0], point1[1], point2[0], point2[1]), node1, node2))
		res = 0
		dsu = DSU()
		for (d, u, v) in sorted(graph):
			if len(dsu.parents) == len(points) and len(set((dsu.find(x) for x in dsu.parents))) == 1:
				return res
			if dsu.union(u, v):
				res += d
		return res


class UnionFind:

	def __init__(self, n):
		self.parent = [i for i in range(n)]
		self.rank = [1 for _ in range(n)]

	def find(self, x):
		if self.parent[x] != x:
			self.parent[x] = self.find(self.parent[x])
		return self.parent[x]

	def union(self, x, y):
		xRoot = self.find(x)
		yRoot = self.find(y)
		if xRoot == yRoot:
			return
		if self.rank[xRoot] > self.rank[yRoot]:
			self.parent[yRoot] = xRoot
			self.rank[xRoot] += self.rank[yRoot]
		else:
			self.parent[xRoot] = yRoot
			self.rank[yRoot] += self.rank[xRoot]

class Solution:

	def minCostConnectPoints(self, points) -> int:
		n = len(points)
		uf = UnionFind(n)
		edges = []
		for i in range(n):
			for j in range(i + 1, n):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				heappush(edges, (dist, i, j))
		totalCost = 0
		while edges:
			(dist, i, j) = heappop(edges)
			if uf.find(i) != uf.find(j):
				totalCost += dist
				uf.union(i, j)
		return totalCost


from collections import defaultdict

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		cost = 0
		n = len(points)
		edges = [[3000000, 0] for i in range(n * (n - 1) // 2)]
		idx = 0
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				edges[idx] = [abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j]
				idx += 1
		edges.sort()
		ret = 0
		i = 0
		k = 0
		child = defaultdict(lambda : [])
		while i < n - 1:
			noCycle = True
			visited = {}
			stack = [[edges[k][1], -1], [edges[k][2], -1]]
			while len(stack) > 0:
				node = stack.pop()
				if node[0] in visited:
					noCycle = False
					break
				else:
					for ch in child[node[0]]:
						if ch != node[1]:
							stack.append([ch, node[0]])
					visited[node[0]] = True
			if noCycle:
				i += 1
				ret += edges[k][0]
				child[edges[k][1]].append(edges[k][2])
				child[edges[k][2]].append(edges[k][1])
			k += 1
		return ret


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		ret = 0
		dis = {}
		for i in range(1, len(points)):
			dis[tuple(points[i])] = abs(points[i][0] - points[0][0]) + abs(points[i][1] - points[0][1])
		while len(dis) > 0:
			minD = min(dis.values())
			for (k, v) in dis.items():
				if v == minD:
					toDel = k
					break
			ret += minD
			del dis[toDel]
			for (k, v) in dis.items():
				dis[k] = min(dis[k], abs(k[0] - toDel[0]) + abs(k[1] - toDel[1]))
		return ret


class UnionFind:

	def __init__(self, n):
		self.size = n
		self.parents = [i for i in range(self.size)]
		self.rank = [1 for _ in range(self.size)]

	def find_parent(self, node):
		if self.parents[node] != node:
			self.parents[node] = self.find_parent(self.parents[node])
		return self.parents[node]

	def union(self, a, b):
		parent_a = self.find_parent(a)
		parent_b = self.find_parent(b)
		if parent_a == parent_b:
			return
		if self.rank[parent_a] < self.rank[parent_b]:
			(parent_a, parent_b) = (parent_b, parent_a)
		self.parents[parent_b] = parent_a
		self.rank[parent_a] += self.rank[parent_b]

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def build_graph(points):
			result = []
			distance = lambda a, b: abs(a[0] - b[0]) + abs(a[1] - b[1])
			for i in range(len(points)):
				for j in range(i + 1, len(points)):
					weight = distance(points[i], points[j])
					result.append((weight, i, j))
			return result
		union_find = UnionFind(len(points))
		graph = build_graph(points)
		graph.sort()
		cost = 0
		for (w, a, b) in graph:
			if union_find.find_parent(a) == union_find.find_parent(b):
				continue
			union_find.union(a, b)
			cost += w
		return cost


class UnionFind:

	def __init__(self, n):
		self.parents = list(range(n))

	def root(self, x):
		if self.parents[x] != x:
			self.parents[x] = self.root(self.parents[x])
		return self.parents[x]

	def union(self, x, y):
		self.parents[self.root(x)] = self.root(y)

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def manh(x1, x2, y1, y2):
			return abs(x1 - x2) + abs(y1 - y2)
		(n, q) = (len(points), [])
		for i in range(n):
			for j in range(i + 1, n):
				heapq.heappush(q, (manh(points[i][0], points[j][0], points[i][1], points[j][1]), i, j))
		cost = 0
		s = UnionFind(n)
		while q:
			(d, i, j) = heapq.heappop(q)
			if s.root(i) != s.root(j):
				s.union(i, j)
				cost += d
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def l1(p1, p2):
			(xi, yi) = p1
			(xj, yj) = p2
			return abs(xi - xj) + abs(yi - yj)
		inf = float('inf')
		LV = len(points)
		E = [(u, v, l1(points[u], points[v])) for u in range(LV) for v in range(LV) if u != v]
		E = sorted(E, key=lambda x: x[2])
		parent = [0] * LV

		def make_set(v):
			parent[v] = v

		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:
				parent[b] = a
		for v in range(LV):
			make_set(v)
		cost = 0
		for (u, v, d) in E:
			if (a := find_set(u)) != (b := find_set(v)):
				cost += d
				union_sets(a, b)
		return cost


import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		(hq, d, s) = ([(0, 0)], [1] * n, 0)
		while hq:
			(t, i) = heapq.heappop(hq)
			if d[i]:
				(s, d[i]) = (s + t, 0)
				for j in range(n):
					if d[j]:
						heapq.heappush(hq, (abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), j))
		return s


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if not points or len(points) <= 1:
			return 0
		heap = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				p1 = points[i]
				p2 = points[j]
				dis = abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
				heapq.heappush(heap, (dis, i, j))
		self.father = [i for i in range(len(points))]
		res = 0
		while heap:
			(dis, u, v) = heapq.heappop(heap)
			root_u = self.find(u)
			root_v = self.find(v)
			if root_u == root_v:
				continue
			self.father[max(root_u, root_v)] = min(root_u, root_v)
			res += dis
		return res

	def find(self, x):
		if self.father[x] == x:
			return self.father[x]
		self.father[x] = self.find(self.father[x])
		return self.father[x]


from collections import defaultdict
from dataclasses import dataclass, field

@dataclass
class Edge:
	src: int
	dst: int
	weight: int

@dataclass
class Graph:
	num_nodes: int
	edgelist: list
	parent: list = field(default_factory=list)
	rank: list = field(default_factory=list)
	mst: list = field(default_factory=list)

	def FindParent(self, node):
		if self.parent[node] == node:
			return node
		return self.FindParent(self.parent[node])

	def KruskalMST(self):
		self.edgelist.sort(key=lambda Edge: Edge.weight)
		self.parent = [None] * self.num_nodes
		self.rank = [None] * self.num_nodes
		for n in range(self.num_nodes):
			self.parent[n] = n
			self.rank[n] = 0
		for edge in self.edgelist:
			root1 = self.FindParent(edge.src)
			root2 = self.FindParent(edge.dst)
			if root1 != root2:
				self.mst.append(edge)
				if self.rank[root1] < self.rank[root2]:
					self.parent[root1] = root2
					self.rank[root2] += 1
				else:
					self.parent[root2] = root1
					self.rank[root1] += 1
		ret = 0
		for edge in self.mst:
			ret += edge.weight
		return ret

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		edges = []
		for i in range(n - 1):
			for j in range(i + 1, n):
				dis = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				edges.append(Edge(i, j, dis))
		g = Graph(n, edges)
		return g.KruskalMST()


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if not points:
			return 0
		cost = 0
		graph = defaultdict(dict)
		for i in range(len(points)):
			for j in range(len(points)):
				if i != j:
					graph[i][j] = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
					graph[j][i] = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
		visited = set()
		graph[-1][0] = 0
		pq = [(0, -1, 0)]
		heapq.heapify(pq)
		while pq:
			if len(visited) == len(points):
				return cost
			(edge_cost, u, v) = heapq.heappop(pq)
			if v not in visited:
				cost += edge_cost
			visited.add(v)
			for nbr in graph[v]:
				if nbr not in visited:
					heapq.heappush(pq, (graph[v][nbr], v, nbr))
		return cost


class DSU:

	def __init__(self, N):
		self.par = list(range(N))
		self.sz = [1] * N

	def find(self, x):
		if self.par[x] != x:
			self.par[x] = self.find(self.par[x])
		return self.par[x]

	def union(self, x, y):
		(xr, yr) = (self.find(x), self.find(y))
		if xr == yr:
			return False
		if self.sz[xr] < self.sz[yr]:
			(xr, yr) = (yr, xr)
		self.par[yr] = xr
		self.sz[xr] += self.sz[yr]
		return True

class Solution:

	def minCostConnectPoints(self, A: List[List[int]]) -> int:
		dict = {}
		for (index, i) in enumerate(A):
			dict[str(i)] = index
		res = 0
		edges = []
		for (index, i) in enumerate(A):
			for j in A[index + 1:]:
				x = abs(i[0] - j[0]) + abs(i[1] - j[1])
				y = dict.get(str(i))
				z = dict.get(str(j))
				edges.append([x, y, z])
		edges.sort()
		arr = DSU(len(A))
		for i in edges:
			if arr.union(i[1], i[2]):
				res += i[0]
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []
		for i in range(len(points)):
			p1 = tuple(points[i])
			for j in range(i + 1, len(points)):
				p2 = tuple(points[j])
				dist = abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
				edges.append((dist, p1, p2))
		edges.sort()
		self.roots = {(x, y): (x, y) for (x, y) in points}
		self.ranks = {(x, y): 0 for (x, y) in points}
		ans = 0
		for edge in edges:
			(dist, p1, p2) = edge
			if self.union(p1, p2):
				ans += dist
		return ans

	def union(self, p1, p2):
		(p1_root, p2_root) = (self.find(p1), self.find(p2))
		if p1_root == p2_root:
			return False
		if self.ranks[p1_root] < self.ranks[p2_root]:
			self.roots[p1_root] = p2_root
		elif self.ranks[p1_root] > self.ranks[p2_root]:
			self.roots[p2_root] = p1_root
		else:
			self.roots[p1_root] = p2_root
			self.ranks[p2_root] += 1
		return True

	def find(self, p):
		if p != self.roots[p]:
			self.roots[p] = self.find(self.roots[p])
		return self.roots[p]


class DSU:

	def __init__(self, N):
		self.p = [i for i in range(N)]

	def find(self, x):
		if self.p[x] != x:
			self.p[x] = self.find(self.p[x])
		return self.p[x]

	def union(self, x, y):
		px = self.find(x)
		py = self.find(y)
		self.p[py] = px

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		heap = []
		result = 0
		n = len(points)
		for i in range(n - 1):
			for j in range(i + 1, n):
				heapq.heappush(heap, (abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j))
		dsu = DSU(n)
		while heap:
			(d, i, j) = heapq.heappop(heap)
			pi = dsu.find(i)
			pj = dsu.find(j)
			if pi != pj:
				result += d
				dsu.union(i, j)
		return result


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		dis = {}
		length = len(points)
		for i in range(length):
			dis[i] = []
		res = 0
		for i in range(length):
			for j in range(length):
				if i == j:
					continue
				d = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				heapq.heappush(dis[i], (d, j))
		visited = set([0])
		res = 0
		while len(visited) < length:
			curMin = -1
			for p in visited:
				while dis[p][0][1] in visited:
					heapq.heappop(dis[p])
				if curMin == -1 or dis[p][0][0] < dis[curMin][0][0]:
					curMin = p
			visited.add(dis[curMin][0][1])
			res += dis[curMin][0][0]
			heapq.heappop(dis[curMin])
		return res


class Solution:

	def minCostConnectPoints(self, points):
		distance = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		points.sort(key=lambda p: p[0] + p[1])
		total_cost = 0
		points = [[p, distance(p, points[0])] for p in points]
		while points:
			(minIdx, mindist) = (None, float('inf'))
			for (i, (p1, dist)) in enumerate(points):
				if dist < mindist:
					(minIdx, mindist) = (i, dist)
			(p1, cost) = points.pop(minIdx)
			total_cost += cost
			for (i, (p2, dist)) in enumerate(points):
				points[i][1] = min(points[i][1], distance(p1, p2))
		return total_cost
from heapq import *
from collections import defaultdict

class Solution:

	def minCostConnectPoints(self, points):
		N = len(points)
		dist = lambda p1, p2: abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		edges = defaultdict(list)
		for (i1, p1) in enumerate(points):
			for (i2, p2) in enumerate(points[i1 + 1:], start=i1 + 1):
				distance = dist(p1, p2)
				edges[i1].append([distance, i2])
				edges[i2].append([distance, i1])
		heap = edges[0]
		heapify(heap)
		(total_cost, seen) = (0, {0})
		while len(seen) < N:
			(cost, node) = heappop(heap)
			if node in seen:
				continue
			seen.add(node)
			total_cost += cost
			for (dist, next_) in edges[node]:
				if next_ not in seen:
					heappush(heap, [dist, next_])
		return total_cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		from queue import PriorityQueue
		coors = {}
		count = 0
		for point in points:
			coors[count] = tuple(point)
			count = count + 1
		pq = PriorityQueue()
		pq.put((0, 0))
		visited = set()
		total = 0
		while len(visited) < len(points):
			(cost, nodeIdx) = pq.get()
			if nodeIdx in visited:
				continue
			total = total + cost
			visited.add(nodeIdx)
			node = coors[nodeIdx]
			for nextNodeIdx in range(len(points)):
				if nextNodeIdx not in visited:
					nextNode = coors[nextNodeIdx]
					nextCost = abs(nextNode[0] - node[0]) + abs(nextNode[1] - node[1])
					pq.put((nextCost, nextNodeIdx))
		return total


class Subsets:

	def __init__(self, parent, rank):
		self.parent = parent
		self.rank = rank

def find(subsets, node):
	if subsets[node].parent != node:
		subsets[node].parent = find(subsets, subsets[node].parent)
	return subsets[node].parent

def union(subsets, x, y):
	xr = find(subsets, x)
	yr = find(subsets, y)
	if xr == yr:
		return False
	else:
		xr = subsets[xr]
		yr = subsets[yr]
		if xr.rank < yr.rank:
			xr.parent = yr.parent
		elif yr.rank < xr.rank:
			yr.parent = xr.parent
		else:
			xr.parent = yr.parent
			yr.rank += 1
		return True

def distance(p1, p2):
	(x1, y1) = p1
	(x2, y2) = p2
	return abs(x1 - x2) + abs(y1 - y2)

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		subsets = {}
		for (x, y) in points:
			subsets[x, y] = Subsets((x, y), 0)
		edges = []
		for i in range(len(points) - 1):
			p1 = tuple(points[i])
			for j in range(i + 1, len(points)):
				p2 = tuple(points[j])
				edges.append((distance(p1, p2), p1, p2))
		edges.sort()
		ans = 0
		for (w, p1, p2) in edges:
			if union(subsets, p1, p2):
				ans += w
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		h = []
		visited = set()
		dist = lambda a, b: abs(a[0] - b[0]) + abs(a[1] - b[1])
		for i in range(len(points)):
			for j in range(i):
				h.append((dist(points[i], points[j]), i, j))
		heapq.heapify(h)
		total = 0
		uf = UnionFind([i for i in range(len(points))])
		while h and len(visited) < len(points):
			(dist, i, j) = heapq.heappop(h)
			if uf.find(i) != uf.find(j):
				uf.union(i, j)
				total += dist
		return total

class UnionFind:

	def __init__(self, arr):
		self.parent = [i for i in range(len(arr))]
		self.rank = [0] * len(arr)

	def find(self, i):
		if self.parent[i] == i:
			return i
		p = self.find(self.parent[i])
		self.parent[i] = p
		return p

	def union(self, a, b):
		(pa, pb) = (self.find(a), self.find(b))
		if self.rank[pa] > self.rank[pb]:
			self.parent[pb] = pa
		elif self.rank[pb] > self.rank[pa]:
			self.parent[pa] = pb
		else:
			self.parent[pb] = pa
			self.rank[pa] += 1


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		costs = []
		for i in range(len(points)):
			(xi, yi) = points[i]
			for j in range(i + 1, len(points)):
				(xj, yj) = points[j]
				costs.append([abs(xi - xj) + abs(yi - yj), i, j])
		costs = sorted(costs)
		fathers = {t: t for t in range(len(points))}

		def get_father(n):
			while not fathers[n] == fathers[fathers[n]]:
				fathers[n] = fathers[fathers[n]]
			return fathers[n]
		to_ret = 0
		for t in costs:
			(ct, pi, pj) = t
			if get_father(pi) == get_father(pj):
				continue
			fathers[get_father(pj)] = get_father(pi)
			to_ret += ct
		return to_ret


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def find(u):
			if p[u] == -1:
				return u
			p[u] = find(p[u])
			return p[u]

		def union(u, v):
			if r[u] > r[v]:
				p[v] = u
			elif r[u] < r[v]:
				p[u] = v
			else:
				p[v] = u
				r[u] += 1
		n = len(points)
		edges = []
		for i in range(n):
			for j in range(i + 1, n):
				edges.append([abs(points[j][0] - points[i][0]) + abs(points[j][1] - points[i][1]), i, j])
		edges.sort()
		p = [-1] * n
		r = [0] * n
		res = 0
		for x in edges:
			u = find(x[1])
			v = find(x[2])
			if u != v:
				res += x[0]
				union(u, v)
		return res


import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def distance(p1, p2):
			return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		L = len(points)
		if L <= 1:
			return 0
		todo = set(range(L))
		nex = 0
		h = []
		ans = 0
		while todo:
			todo.remove(nex)
			for i in todo:
				heapq.heappush(h, (distance(points[nex], points[i]), i))
			while h and h[0][1] not in todo:
				heapq.heappop(h)
			if not h:
				break
			(cost, nex) = heapq.heappop(h)
			ans += cost
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		d = collections.defaultdict(list)
		m = {}
		for i in range(len(points)):
			m[points[i][0], points[i][1]] = i
		h = []
		for i in range(len(points) - 1):
			for j in range(i + 1, len(points)):
				(x1, y1) = (points[i][0], points[i][1])
				(x2, y2) = (points[j][0], points[j][1])
				k = self.manhattan(x1, y1, x2, y2)
				d[m[x1, y1]].append([m[x2, y2], k])
				d[m[x2, y2]].append([m[x1, y1], k])
		ans = 0
		h = []
		for (n, w) in d[0]:
			h.append([w, n])
		heapq.heapify(h)
		seen = set({0})
		while h:
			(w, n) = heapq.heappop(h)
			if n in seen:
				continue
			seen.add(n)
			ans += w
			if len(seen) == len(points):
				break
			for (n2, w2) in d[n]:
				heapq.heappush(h, [w2, n2])
		return ans

	def manhattan(self, x1, y1, x2, y2):
		return abs(x2 - x1) + abs(y2 - y1)


class UnionFind(object):

	def __init__(self, n):
		self.count = n
		self.parent = [i for i in range(n)]
		self.rank = [1 for _ in range(n)]

	def find(self, p):
		if p != self.parent[p]:
			self.parent[p] = self.find(self.parent[p])
		return self.parent[p]

	def union(self, p, q):
		(p_root, q_root) = (self.find(p), self.find(q))
		if p_root == q_root:
			return False
		if self.rank[p_root] > self.rank[q_root]:
			(p_root, q_root) = (q_root, p_root)
		self.parent[p_root] = q_root
		self.rank[q_root] += self.rank[p_root]
		self.count -= 1
		return True

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		uf = UnionFind(n)

		def manhattan(p1, p2):
			return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		g = collections.defaultdict(list)
		n = len(points)
		heap = []
		for i in range(n):
			for j in range(i + 1, n):
				distance = manhattan(points[i], points[j])
				heap.append((distance, i, j))
		res = 0
		heapq.heapify(heap)
		while heap:
			(weight, i, j) = heapq.heappop(heap)
			if uf.union(i, j):
				res += weight
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		N = len(points)
		dist = [math.inf] * N
		prev_node = 0
		res = 0

		def getDistance(x, y):
			return abs(points[x][0] - points[y][0]) + abs(points[x][1] - points[y][1])
		for _ in range(N):
			(min_dist, min_dist_node) = (math.inf, -1)
			for i in range(N):
				if dist[i] != None:
					dist[i] = min(dist[i], getDistance(prev_node, i))
					if dist[i] < min_dist:
						(min_dist, min_dist_node) = (dist[i], i)
			res += min_dist
			prev_node = min_dist_node
			dist[prev_node] = None
		return res


class DSU:

	def __init__(self, N):
		self.parent = list(range(N))

	def find(self, x):
		if self.parent[x] != x:
			self.parent[x] = self.find(self.parent[x])
		return self.parent[x]

	def union(self, x, y):
		(xr, yr) = (self.find(x), self.find(y))
		if xr == yr:
			return False
		self.parent[yr] = xr
		return True

class Solution:

	def minCostConnectPoints(self, P: List[List[int]]) -> int:
		from collections import defaultdict
		connections = []
		for i in range(len(P)):
			for j in range(i + 1, len(P)):
				if i != j:
					cost = abs(P[i][0] - P[j][0]) + abs(P[i][1] - P[j][1])
					connections.append([i, j, cost])
		connections = list(connections)
		connections.sort(key=lambda x: x[2])
		dsu = DSU(len(P))
		res = 0
		for (u, v, w) in connections:
			curr = dsu.union(u, v)
			if curr:
				res += w
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		dic = {}
		for i in range(len(points)):
			val = []
			for j in range(len(points)):
				if points[j] != points[i]:
					val = abs(points[j][0] - points[i][0]) + abs(points[j][1] - points[i][1])
					dic[i, j] = val
		g = Graph(len(points))
		for (k, v) in list(dic.items()):
			g.addEdge(k[0], k[1], v)
		res = g.KruskalMST()
		print(res)
		return res

class Graph:

	def __init__(self, vertices):
		self.v = vertices
		self.graph = []

	def addEdge(self, u, v, w):
		self.graph.append([u, v, w])

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

	def union(self, parent, x, y):
		x_set = self.find(parent, x)
		y_set = self.find(parent, y)
		parent[x_set] = y_set

	def KruskalMST(self):
		MST = []
		i = 0
		e = 0
		self.graph = sorted(self.graph, key=lambda e: e[2])
		parent = [-1] * self.v
		while e < self.v - 1:
			(u, v, w) = self.graph[i]
			i += 1
			x = self.find(parent, u)
			y = self.find(parent, v)
			if x != y:
				e += 1
				MST.append([u, v, w])
				self.union(parent, x, y)
		s = 0
		for (u, v, w) in MST:
			s += w
		return s


from heapq import heappush, heappop
from collections import defaultdict

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def taxicab(x1, x2, y1, y2):
			return abs(x1 - x2) + abs(y1 - y2)

		def gengraph():
			graph = defaultdict(list)
			for (i, point) in enumerate(points):
				(x1, y1) = point
				for j in range(i + 1, len(points)):
					(x2, y2) = points[j]
					cost = taxicab(x1, x2, y1, y2)
					graph[x1, y1].append((cost, (x2, y2)))
					graph[x2, y2].append((cost, (x1, y1)))
			return graph
		graph = gengraph()
		relaxed = set()
		start = tuple(points[0])
		heap = [(0, start)]
		mincost = 0
		while heap and len(relaxed) < len(points):
			(cost, pos) = heappop(heap)
			if pos in relaxed:
				continue
			relaxed.add(pos)
			mincost += cost
			for nbr in graph[pos]:
				if nbr not in relaxed:
					heappush(heap, nbr)
		return mincost


from collections import defaultdict
import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		(total, heap, visited) = (0, [(0, 0)], set())
		distances = defaultdict(list)
		for i in range(len(points) - 1):
			for j in range(1, len(points)):
				distances[i].append((self.distance(points[i], points[j]), j))
				distances[j].append((self.distance(points[i], points[j]), i))
		while heap and len(visited) < len(points):
			(distance, point) = heapq.heappop(heap)
			if point not in visited:
				visited.add(point)
				total += distance
				for (neighbor_distance, neighbor) in distances[point]:
					if neighbor not in visited:
						heapq.heappush(heap, (neighbor_distance, neighbor))
		return total

	def distance(self, pair1, pair2):
		return abs(pair1[0] - pair2[0]) + abs(pair1[1] - pair2[1])


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		N = len(points)
		root = list(range(N))
		size = [1] * N
		res = 0

		def find(x):
			root[x] = find(root[x]) if root[x] != x else root[x]
			return root[x]

		def union(x, y):
			(x, y) = (find(x), find(y))
			if x == y:
				return False
			if size[x] < size[y]:
				(x, y) = (y, x)
			root[y] = x
			size[x] += size[y]
			return True
		edge_ls = []
		for (i, cur) in enumerate(points):
			for (j, nxt) in enumerate(points[i + 1:]):
				dist = abs(cur[0] - nxt[0]) + abs(cur[1] - nxt[1])
				edge_ls.append([dist, i, i + j + 1])
		edge_ls.sort()
		for (dist, u, v) in edge_ls:
			if find(u) != find(v):
				res += dist
				union(u, v)
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def hash_point(point):
			return (point[0], point[1])

		def manh_dist(point1, point2):
			return abs(point1[0] - point2[0]) + abs(point1[1] - point2[1])
		if len(points) == 1:
			return 0
		if len(points) == 2:
			return manh_dist(points[0], points[1])
		points_remaining = set()
		dists = []
		first_point = points[0]
		for i in range(1, len(points)):
			(point, h_point) = (points[i], hash_point(points[i]))
			points_remaining.add(h_point)
			heapq.heappush(dists, (manh_dist(first_point, point), h_point))
		ans = 0
		while points_remaining and dists:
			(dist, point) = heapq.heappop(dists)
			if point not in points_remaining:
				continue
			points_remaining.remove(point)
			ans += dist
			for p in points_remaining:
				heapq.heappush(dists, (manh_dist(point, p), p))
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []
		arr = [-1 for _ in range(len(points))]

		def find(i):
			while arr[i] >= 0:
				i = arr[i]
			return i

		def union(x, y):
			xp = find(x)
			yp = find(y)
			if xp == yp:
				return False
			arr[yp] = xp
			return True
		for i in range(len(points)):
			(x, y) = points[i]
			for j in range(i + 1, len(points)):
				(x1, y1) = points[j]
				edges.append([abs(x - x1) + abs(y - y1), i, j])
		edges = sorted(edges)
		res = 0
		for (score, i, j) in edges:
			if union(i, j):
				res += score
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		edges = []
		for (i, p1) in enumerate(points):
			for j in range(i, len(points)):
				p2 = points[j]
				d = abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
				edges.append([d, i, j])
		edges = sorted(edges)
		u = {i: i for i in range(n)}

		def head(i):
			if u[i] == i:
				return i
			else:
				h = head(u[i])
				u[i] = h
				return h

		def union(i, j):
			u[head(j)] = head(i)
		r = 0
		for (d, i, j) in edges:
			(hi, hj) = (head(i), head(j))
			if hi != hj:
				r += d
				union(hi, hj)
		return r


class UnionFind:

	def __init__(self, n):
		self.groups = list(range(n))
		self.size = [1] * n

	def find(self, i):
		if self.groups[i] == i:
			return i
		p = self.find(self.groups[i])
		self.groups[i] = p
		return p

	def union(self, i, j):
		pi = self.find(i)
		pj = self.find(j)
		if self.size[pi] < self.size[pj]:
			self.groups[pi] = pj
			self.size[pj] += self.size[pi]
		else:
			self.groups[pj] = pi
			self.size[pi] += self.size[pj]

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		cost_array = []
		for i in range(len(points) - 1):
			for j in range(i + 1, len(points)):
				weight = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				cost_array.append((weight, i, j))
		cost_array.sort()
		res = 0
		uf = UnionFind(len(points))
		for (weight, i, j) in cost_array:
			if uf.find(i) == uf.find(j):
				continue
			uf.union(i, j)
			res += weight
		return res


class Solution:

	def minCostConnectPoints(self, A: List[List[int]]) -> int:
		N = len(A)
		P = [i for i in range(N)]
		E = []
		for i in range(N):
			(x1, y1) = A[i]
			for j in range(i + 1, N):
				(x2, y2) = A[j]
				E.append([abs(x1 - x2) + abs(y1 - y2), i, j])
		E.sort()

		def find(x):
			P[x] = P[x] if P[x] == x else find(P[x])
			return P[x]

		def union(a, b):
			a = find(a)
			b = find(b)
			if a == b:
				return False
			P[a] = b
			return True
		return sum([cost for (cost, u, v) in E if union(u, v)])


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		data = [i for i in range(len(points))]
		pq = []
		res = 0

		def helper(p1, p2):
			return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])

		def find(x):
			if x != data[x]:
				data[x] = find(data[x])
			return data[x]

		def union(x, y):
			root_x = find(x)
			root_y = find(y)
			if root_x == root_y:
				return False
			data[root_x] = root_y
			return True
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				heapq.heappush(pq, (helper(points[i], points[j]), i, j))
		res = 0
		while pq:
			(cost, p1, p2) = heapq.heappop(pq)
			if union(p1, p2):
				res += cost
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		if n == 1:
			return 0
		e = []
		for (i, p1) in enumerate(points):
			for j in range(i + 1, n):
				p2 = points[j]
				w = abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
				e.append((i, j, w))
				e.append((j, i, w))
		parents = [i for i in range(n)]
		ranks = [1 for _ in range(n)]

		def find(x):
			while x != parents[x]:
				parents[x] = parents[parents[x]]
				x = parents[x]
			return x

		def union(x, y):
			(px, py) = (find(x), find(y))
			if px == py:
				return False
			if ranks[px] > ranks[py]:
				parents[py] = px
			elif ranks[px] < ranks[py]:
				parents[px] = py
			else:
				parents[py] = px
				ranks[px] += 1
			return True
		res = 0
		for (u, v, w) in sorted(e, key=lambda x: x[2]):
			if not union(u, v):
				continue
			else:
				res += w
		return res


class Solution:

	def addEdge(self, source, dest, weight):
		self.graph.append([tuple(source), tuple(dest), weight])

	def getParent(self, vertex):
		if vertex == self.parent[vertex]:
			return vertex
		return self.getParent(self.parent[vertex])

	def joinTrees(self, u, v):
		xroot = self.getParent(u)
		yroot = self.getParent(v)
		if self.rank[xroot] > self.rank[yroot]:
			self.parent[yroot] = xroot
		elif self.rank[yroot] < self.rank[xroot]:
			self.parent[xroot] = yroot
		else:
			self.parent[yroot] = xroot
			self.rank[yroot] += 1

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		self.graph = []
		for i in range(0, len(points)):
			for j in range(i + 1, len(points)):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				self.addEdge(points[i], points[j], dist)
		self.V = len(points)
		e = 0
		self.parent = {tuple(points[i]): tuple(points[i]) for i in range(0, len(points))}
		self.rank = {tuple(points[i]): 0 for i in range(0, len(points))}
		self.graph = sorted(self.graph, key=lambda x: x[2])
		i = 0
		tot = 0
		while e < self.V - 1:
			(u, v, w) = self.graph[i]
			i += 1
			uroot = self.getParent(u)
			vroot = self.getParent(v)
			if uroot != vroot:
				self.joinTrees(u, v)
				tot += w
				e += 1
		return tot


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def pdist(i, j):
			return abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
		N = len(points)
		pvisited = [False] * N
		h = []
		mincost = 0
		heappush(h, (0, 0))
		while h:
			(dist, el) = heappop(h)
			if not pvisited[el]:
				pvisited[el] = True
				mincost += dist
				for i in range(N):
					if not pvisited[i]:
						heappush(h, (pdist(el, i), i))
		return mincost


class DSU:

	def __init__(self, n):
		self.par = list(range(n))

	def find(self, x):
		if self.par[x] != x:
			self.par[x] = self.find(self.par[x])
		return self.par[x]

	def union(self, x, y):
		px = self.find(x)
		py = self.find(y)
		if px != py:
			self.par[px] = py

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) <= 1:
			return 0

		def dist(x1, y1, x2, y2):
			return abs(x2 - x1) + abs(y2 - y1)
		lens = []
		res = 0
		n = len(points)
		dsu = DSU(n)
		for i in range(n - 1):
			for j in range(i + 1, n):
				lens.append((dist(points[i][0], points[i][1], points[j][0], points[j][1]), i, j))
		heapq.heapify(lens)
		while lens:
			(dist, i, j) = heapq.heappop(lens)
			if dsu.find(i) != dsu.find(j):
				dsu.union(i, j)
				res += dist
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) == 1:
			return 0

		def get_dist(p1, p2):
			return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		(seen, res) = (set([0]), 0)
		heap = [(get_dist(points[0], p2), i + 1) for (i, p2) in enumerate(points[1:])]
		heapq.heapify(heap)
		while heap:
			(dist, index) = heapq.heappop(heap)
			if index in seen:
				continue
			seen.add(index)
			res += dist
			for i in range(len(points)):
				if i != index and i not in seen:
					heapq.heappush(heap, (get_dist(points[i], points[index]), i))
		return res


class Solution:

	def __init__(self):
		self.parent = dict()
		self.rank = dict()

	def find(self, x: int) -> int:
		if self.parent[x] != x:
			self.parent[x] = self.find(self.parent[x])
		return self.parent[x]

	def union(self, x: int, y: int) -> None:
		if self.rank[x] > self.rank[y]:
			self.parent[y] = x
		elif self.rank[y] > self.rank[x]:
			self.parent[x] = y
		else:
			self.rank[x] += 1
			self.parent[y] = x

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		l = len(points)
		ans = 0
		if l > 1:
			heap = list()
			for i in range(l - 1):
				self.parent[i] = i
				self.rank[i] = 0
				for j in range(i + 1, l):
					heap.append((abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j))
			self.parent[l - 1] = l - 1
			self.rank[l - 1] = 0
			heapq.heapify(heap)
			while heap:
				(dis, x, y) = heapq.heappop(heap)
				if self.find(x) != self.find(y):
					ans += dis
					self.union(self.find(x), self.find(y))
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		self.parent = list(range(len(points)))
		self.rank = [1] * len(points)

		def find(a):
			if self.parent[a] != a:
				self.parent[a] = find(self.parent[a])
			return self.parent[a]

		def union(a, b):
			p1 = find(a)
			p2 = find(b)
			if p1 == p2:
				return False
			if self.rank[p1] > self.rank[p2]:
				self.parent[p2] = p1
			elif self.rank[p1] < self.rank[p2]:
				self.parent[p1] = p2
			else:
				self.parent[p1] = p2
				self.rank[p2] += 1
			return True

		def dist(a, b):
			return abs(a[0] - b[0]) + abs(a[1] - b[1])
		weights = {}
		edges = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				weights[i, j] = dist(points[i], points[j])
				edges.append((i, j))
		edges.sort(key=lambda x: weights[x])
		ans = 0
		for e in edges:
			if union(e[0], e[1]):
				ans += weights[e]
		return ans


class DSU:

	def __init__(self, n):
		self.parents = list(range(n))
		self.cc = n

	def find(self, u):
		orig = u
		while u != self.parents[u]:
			u = self.parents[u]
		self.parents[orig] = u
		return u

	def union(self, u, v):
		(u, v) = sorted([self.find(u), self.find(v)])
		if u != v:
			self.parents[v] = u
			self.cc -= 1
			return True
		return False

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		distances = {}

		def compute(p1, p2):
			(x1, y1) = p1
			(x2, y2) = p2
			return abs(x1 - x2) + abs(y1 - y2)
		heap = []
		for (i, p1) in enumerate(points):
			for j in range(i + 1, len(points)):
				p2 = points[j]
				heapq.heappush(heap, (compute(p1, p2), i, j))
		dsu = DSU(len(points))
		res = 0
		while heap:
			(d, u, v) = heapq.heappop(heap)
			if dsu.union(u, v):
				res += d
		return res


from queue import PriorityQueue

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		q = PriorityQueue()
		(x0, y0) = points[0]
		for (x, y) in points[1:]:
			q.put([abs(x - x0) + abs(y - y0), x, y])
		cost = 0
		to_process = set([(x, y) for (x, y) in points[1:]])
		while len(to_process) > 0:
			(d, x, y) = q.get()
			if (x, y) not in to_process:
				continue
			to_process.remove((x, y))
			cost += d
			for (nx, ny) in to_process:
				q.put([abs(x - nx) + abs(y - ny), nx, ny])
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		ans = 0
		mx = -1
		inc = set()
		d = {}
		parent = []
		rank = []
		result = []
		i = 0
		e = 0
		nodes = {}
		idx = 0
		for i in range(n):
			nodes[idx] = (points[i][0], points[i][1])
			idx += 1
		graph = []
		for i in range(n):
			d[i] = []
			for j in range(n):
				if i == j:
					continue
				graph.append([i, j, abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])])
		graph.sort(key=lambda x: x[2])

		def find(parent, i):
			if parent[i] == i:
				return i
			return find(parent, parent[i])

		def union(parent, rank, x, y):
			xroot = find(parent, x)
			yroot = find(parent, y)
			if rank[xroot] < rank[yroot]:
				parent[xroot] = yroot
			elif rank[yroot] < rank[xroot]:
				parent[yroot] = xroot
			else:
				parent[yroot] = xroot
				rank[xroot] += 1
		for node in range(n):
			parent.append(node)
			rank.append(0)
		i = 0
		ans = 0
		while e < n - 1:
			(u, v, w) = graph[i]
			i += 1
			x = find(parent, u)
			y = find(parent, v)
			if x != y:
				e = e + 1
				ans += w
				union(parent, rank, x, y)
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		res = 0
		n = len(points)
		dist = [0] * n

		def distance(px, py):
			return abs(px[0] - py[0]) + abs(px[1] - py[1])
		for i in range(1, n):
			dist[i] = distance(points[0], points[i])
		flag = [0] * n
		flag[0] = 1
		for i in range(1, n):
			mi = math.inf
			index = -1
			for j in range(1, n):
				if flag[j]:
					continue
				if mi > dist[j]:
					index = j
					mi = dist[j]
			flag[index] = 1
			res += mi
			for j in range(1, n):
				if flag[j]:
					continue
				dist[j] = min(dist[j], distance(points[j], points[index]))
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		l = len(points)
		parent = [i for i in range(l)]

		def find(a):
			if parent[a] != a:
				parent[a] = find(parent[a])
			return parent[a]

		def union(a, b):
			p1 = find(a)
			p2 = find(b)
			parent[p2] = p1
		import heapq

		def new_cmp_lt(self, a, b):
			return a[0] - b[0]
		heapq.cmp_lt = new_cmp_lt
		res = 0
		p = []
		for i in range(l):
			for j in range(i + 1, l):
				p1 = points[i]
				p2 = points[j]
				d = abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
				heapq.heappush(p, [d, i, j])
		while p:
			t = heapq.heappop(p)
			d = t[0]
			p1 = t[1]
			p2 = t[2]
			if find(p1) != find(p2):
				union(p1, p2)
				res += d
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def dist(u, v):
			(x, y) = points[u]
			(x2, y2) = points[v]
			return abs(x - x2) + abs(y - y2)
		n = len(points)
		visited = [False] * n
		pq = [(0, 0)]
		ans = 0
		while pq:
			(cost, u) = heappop(pq)
			if visited[u]:
				continue
			visited[u] = True
			ans += cost
			for v in range(n):
				if visited[v]:
					continue
				heappush(pq, (dist(u, v), v))
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		dist = []
		for i in range(len(points) - 1):
			for j in range(i + 1, len(points)):
				d = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				dist.append([d, i, j])
		dist.sort()
		graph = {i: set() for i in range(len(points))}

		def has_cycle(node, prev, parent):
			if node in prev:
				return True
			prev.add(node)
			for next_node in graph[node]:
				if next_node != parent and next_node in prev:
					return True
				if next_node != parent and has_cycle(next_node, prev, node):
					return True
			return False
		cost = 0
		n_edge = 0
		for (d, i, j) in dist:
			if n_edge == len(points) - 1:
				break
			graph[i].add(j)
			graph[j].add(i)
			if not has_cycle(i, set(), None) and (not has_cycle(j, set(), None)):
				n_edge += 1
				cost += d
			else:
				graph[i].remove(j)
				graph[j].remove(i)
		return cost


import heapq

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def distance(points, i, j) -> int:
			return abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])

		def getGroup(group, x):
			if group[x] == x:
				return x
			group[x] = getGroup(group, group[x])
			return group[x]

		def isCycle(group, cur):
			g1 = getGroup(group, cur[1])
			g2 = getGroup(group, cur[2])
			return g1 == g2

		def unio(group, cur):
			g1 = getGroup(group, cur[1])
			g2 = getGroup(group, cur[2])
			group[g2] = g1
		(pq, group) = ([], [])
		n = len(points)
		for i in range(n):
			group.append(i)
			for j in range(i + 1, n):
				dis = distance(points, i, j)
				heapq.heappush(pq, (dis, i, j))
		(count, rtn) = (0, 0)
		while count < n - 1:
			cur = heapq.heappop(pq)
			if not isCycle(group, cur):
				unio(group, cur)
				rtn += cur[0]
				count += 1
		return rtn


class UnionFind:

	def __init__(self, n):
		self.parent = collections.defaultdict(int)
		for i in range(1, n + 1):
			self.parent[i] = i

	def find(self, i):
		if i != self.parent[i]:
			self.parent[i] = self.find(self.parent[i])
		return self.parent[i]

	def union(self, u, v):
		(u_parent, v_parent) = (self.find(u), self.find(v))
		if u_parent == v_parent:
			return False
		self.parent[u_parent] = v_parent
		return True

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		pq = list()
		heapq.heapify(pq)
		for i in range(n - 1):
			for j in range(i + 1, n):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				heapq.heappush(pq, (dist, i, j))
		res = 0
		uf = UnionFind(n)
		while pq:
			(cost, a, b) = heapq.heappop(pq)
			if uf.find(a) != uf.find(b):
				uf.union(a, b)
				res += cost
		return res


class Solution:

	def minCostConnectPoints(self, A: List[List[int]]) -> int:

		def distance(a, b):
			return abs(a[0] - b[0]) + abs(a[1] - b[1])
		dic = {}

		def find(i):
			dic.setdefault(i, i)
			if dic[i] != i:
				dic[i] = find(dic[i])
			return dic[i]

		def union(i, j):
			(fi, fj) = (find(i), find(j))
			if fi != fj:
				dic[fi] = fj
				return 1
			return 0
		dis = []
		n = len(A)
		for i in range(n):
			for j in range(i + 1, n):
				d = distance(A[i], A[j])
				dis.append([d, i, j])
		dis = sorted(dis)
		(ret, ct) = (0, 0)
		for (d, i, j) in dis:
			if union(i, j):
				ret += d
				ct += 1
				if ct == n:
					break
		return ret


class Union_Find:

	def __init__(self, n):
		self.father = {i: i for i in range(n)}
		self.count = n
		self.rank = [1] * n

	def find(self, x):
		if self.father[x] == x:
			return x
		self.father[x] = self.find(self.father[x])
		return self.father[x]

	def union(self, x, y):
		if self.rank[x] < self.rank[y]:
			(x, y) = (y, x)
		self.father[y] = x
		self.rank[x] += self.rank[y]
		self.count -= 1

	def find_union(self, x, y):
		(father_x, father_y) = (self.find(x), self.find(y))
		if father_x != father_y:
			self.union(father_x, father_y)
			return True
		return False

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		mst = collections.defaultdict(set)
		edges = []
		n = len(points)
		graph = collections.defaultdict(list)
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				if i == j:
					continue
				cost = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				edges.append((cost, i, j))
		uf = Union_Find(n)
		heapq.heapify(edges)
		result = 0
		while edges:
			(cost, frm, to) = heapq.heappop(edges)
			if uf.find_union(frm, to):
				result += cost
				print((frm, to))
		return result


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []

		def dist(a, b):
			return abs(a[0] - b[0]) + abs(a[1] - b[1])
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				edges.append([dist(points[i], points[j]), i, j])
		edges.sort()
		st = set()
		ans = 0
		root_ = [i for i in range(len(points))]
		comp = [1 for i in range(len(points))]

		def root(i):
			while root_[i] != i:
				i = root_[i]
			return i

		def union(i, j):
			if root(i) == root(j):
				return
			else:
				rooti = root(i)
				rootj = root(j)
				if comp[rooti] > comp[rootj]:
					root_[rootj] = rooti
					comp[rooti] += comp[rootj]
				else:
					root_[rooti] = rootj
					comp[rootj] += comp[rooti]
		for i in edges:
			if root(i[1]) == root(i[2]):
				continue
			else:
				union(i[1], i[2])
				ans += i[0]
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)

		def dist(i, j):
			return abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
		heap = []
		for i in range(n - 1):
			for j in range(i + 1, n):
				heap.append((dist(i, j), i, j))
		heapq.heapify(heap)

		def find(i):
			if p[i] != i:
				p[i] = find(p[i])
			return p[i]

		def union(i, j):
			p[find(i)] = find(j)
		p = list(range(n))
		num_edges = 0
		res = 0
		while heap and num_edges < n:
			(d, i, j) = heapq.heappop(heap)
			if find(i) == find(j):
				continue
			union(i, j)
			num_edges += 1
			res += d
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		hq = []
		parent = len(points) * [0]
		cnt = len(points) * [0]
		for i in range(len(points)):
			parent[i] = i
		for i in range(len(points) - 1):
			for j in range(i + 1, len(points)):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				heappush(hq, [dist, i, j])
		visited = {}
		ans = 0

		def find_parent(i):
			if parent[i] == i:
				return i
			else:
				x = find_parent(parent[i])
				parent[i] = x
				return x

		def update_parent(i, j):
			x = find_parent(i)
			y = find_parent(j)
			if cnt[x] < cnt[y]:
				parent[x] = y
				cnt[y] += 1
			else:
				parent[y] = x
				cnt[x] += 1
		while len(hq) != 0:
			ce = heappop(hq)
			if find_parent(ce[1]) != find_parent(ce[2]):
				ans += ce[0]
				update_parent(ce[1], ce[2])
		return ans


class Solution:

	def distance(self, p1, p2):
		return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])

	def build_graph(self, points):
		res = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				res.append([i, j, self.distance(points[i], points[j])])
		return res

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		connections = self.build_graph(points)
		connections.sort(key=lambda x: x[2])
		parents = [i for i in range(len(points))]

		def find(node):
			parent = parents[node]
			while node != parent:
				node = parent
				parent = parents[node]
			return node
		cost = 0
		for edge in connections:
			node1 = edge[0]
			node2 = edge[1]
			curr_cost = edge[2]
			if find(node1) != find(node2):
				parents[find(node2)] = find(node1)
				cost += curr_cost
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def distance(point1, point2):
			return abs(point1[0] - point2[0]) + abs(point1[1] - point2[1])
		n = len(points)
		edges = []
		for i in range(n):
			for j in range(i + 1, n):
				edges.append([distance(points[i], points[j]), i, j])
		edges.sort()
		p = [i for i in range(n)]

		def find(x):
			if p[x] != x:
				p[x] = find(p[x])
			return p[x]

		def union(x, y):
			px = find(x)
			py = find(y)
			if px == py:
				return True
			else:
				p[px] = p[py]
		res = 0
		for edge in edges:
			(d, x, y) = edge
			if union(x, y):
				continue
			else:
				res += d
		return res


from heapq import heappush, heappop

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		dists = [[float('inf')] * n for _ in range(n)]
		for (idx1, point1) in enumerate(points):
			for (idx2, point2) in enumerate(points):
				if idx1 != idx2:
					manhattan = abs(point1[0] - point2[0]) + abs(point1[1] - point2[1])
					dists[idx1][idx2] = manhattan
					dists[idx2][idx1] = manhattan
		res = 0
		nearest = [float('inf')] * n
		visited = set()
		h = [(0, 0)]
		while h and len(visited) < n:
			(last_dist, last_pt) = heappop(h)
			visited.add(last_pt)
			nearest[last_pt] = min(last_dist, nearest[last_pt])
			for (neigh_pt, neigh_dist) in enumerate(dists[last_pt]):
				if neigh_pt not in visited and neigh_dist < nearest[neigh_pt]:
					heappush(h, (neigh_dist, neigh_pt))
		return sum(nearest)


class Point:

	def __init__(self, x, y):
		self.x = x
		self.y = y

	def __lt__(self, other):
		return [self.x, self.y] < [other.x, other.y]

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		points = [Point(x, y) for (x, y) in points]
		edges = []

		def getDistance(a, b):
			return abs(a.x - b.x) + abs(a.y - b.y)
		visited = set()
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				(u, v) = (points[i], points[j])
				edges.append((getDistance(u, v), u, v))
		edges.sort(reverse=True)
		self.parent = {p: p for p in points}
		self.size = {p: 1 for p in points}
		components = len(points)
		total_cost = 0
		while components > 1 and edges:
			(d, u, v) = edges.pop()
			if self.union(u, v):
				total_cost += d
				components -= 1
		return total_cost

	def union(self, a, b):
		root_a = self.find(a)
		root_b = self.find(b)
		if root_a != root_b:
			if self.size[root_a] <= self.size[root_b]:
				self.parent[root_a] = root_b
				self.size[root_b] += self.size[root_a]
			else:
				self.parent[root_b] = root_a
				self.size[root_a] += self.size[root_b]
			return True
		return False

	def find(self, a):
		curr = a
		while self.parent[curr] != curr:
			curr = self.parent[curr]
		(root, curr) = (curr, a)
		while self.parent[curr] != curr:
			(self.parent[curr], curr) = (root, self.parent[curr])
		return root


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def dist(p1, p2):
			(x1, y1) = p1
			(x2, y2) = p2
			return abs(x1 - x2) + abs(y1 - y2)
		import collections
		import heapq
		edges = []
		for i in range(len(points)):
			for j in range(len(points)):
				if i != j:
					edges.append([i, j, dist(points[i], points[j])])

		def primLazy(edges, n):

			def visit(v):
				included[v] = True
				for neighbor in G[v]:
					if not included[neighbor]:
						heapq.heappush(pq, [G[v][neighbor], v, neighbor])
			G = collections.defaultdict(dict)
			for (v, w, weight) in edges:
				G[v][w] = weight
				G[w][v] = weight
			included = [False for i in range(n)]
			mst = []
			pq = []
			visit(points[0])
			d = 0
			while pq:
				(dist, v, w) = heapq.heappop(pq)
				if included[v] and included[w]:
					continue
				mst.append([v, w])
				d += G[v][w]
				if not included[v]:
					visit(v)
				if not included[w]:
					visit(w)
			return mst

		def kruskalSize(edges, n):
			parent = [i for i in range(n)]
			sz = [1 for i in range(n)]

			def find(i):
				while i != parent[i]:
					i = parent[i]
				return i

			def union(x, y):
				(rx, ry) = (find(x), find(y))
				if rx == ry:
					return
				if sz[rx] < sz[ry]:
					parent[rx] = ry
					sz[ry] += sz[rx]
				else:
					parent[ry] = rx
					sz[rx] += sz[ry]
			mst = []
			d = 0
			edges = sorted(edges, key=lambda x: x[2])
			for (v, w, weight) in edges:
				if find(v) != find(w):
					mst.append([v, w])
					d += weight
					union(v, w)
			return d
		return kruskalSize(edges, len(points))


from collections import defaultdict

class Solution:

	def find(self, parent, i):
		if parent[i] == i:
			return i
		return self.find(parent, parent[i])

	def union(self, parent, rank, x, y):
		xroot = self.find(parent, x)
		yroot = self.find(parent, y)
		if rank[xroot] < rank[yroot]:
			parent[xroot] = yroot
		elif rank[xroot] > rank[yroot]:
			parent[yroot] = xroot
		else:
			parent[yroot] = xroot
			rank[xroot] += 1

	def KruskalMST(self):
		result = []
		i = 0
		e = 0
		self.graph = sorted(self.graph, key=lambda item: item[2])
		parent = []
		rank = []
		for node in range(self.V):
			parent.append(node)
			rank.append(0)
		while e < self.V - 1:
			(u, v, w) = self.graph[i]
			i = i + 1
			x = self.find(parent, u)
			y = self.find(parent, v)
			if x != y:
				e = e + 1
				result.append([u, v, w])
				self.union(parent, rank, x, y)
		summ = 0
		for (u, v, weight) in result:
			summ += weight
		return summ

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		self.V = len(points)
		self.graph = []
		for i in range(len(points)):
			for j in range(len(points)):
				md = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				self.graph.append([i, j, md])
		return self.KruskalMST()


class DSU:

	def __init__(self, a):
		self.par = {x: x for x in a}

	def merge(self, u, v):
		rootu = self.find(u)
		rootv = self.find(v)
		if rootu == rootv:
			return False
		self.par[rootv] = rootu
		return True

	def find(self, u):
		if self.par[u] != u:
			self.par[u] = self.find(self.par[u])
		return self.par[u]

class Solution:

	def minCostConnectPoints(self, a: List[List[int]]) -> int:

		def manhattan_dist(u, v):
			return abs(u[0] - v[0]) + abs(u[1] - v[1])
		n = len(a)
		a = [tuple(x) for x in a]
		dsu = DSU(a)
		edges = []
		for (u, v) in combinations(a, 2):
			edges.append((u, v, manhattan_dist(u, v)))
		edges.sort(key=lambda x: x[2])
		ret = 0
		for (u, v, c) in edges:
			if dsu.merge(u, v):
				ret += c
		return ret


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		import heapq
		HQ = []
		heapq.heapify(HQ)
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				dist = abs(points[j][0] - points[i][0]) + abs(points[j][1] - points[i][1])
				heapq.heappush(HQ, (dist, i, j))
		G = list(range(len(points)))

		def find(x):
			if G[x] != x:
				G[x] = find(G[x])
			return G[x]

		def union(x, y):
			(x, y) = (find(x), find(y))
			if x == y:
				return False
			G[x] = y
			return True
		res = 0
		while HQ:
			(curdist, curi, curj) = heapq.heappop(HQ)
			if union(curi, curj):
				res += curdist
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		edges = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				p1 = points[i]
				p2 = points[j]
				l = abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
				edges.append((l, tuple(p1), tuple(p2)))
		trees = []
		for point in points:
			a = set()
			a.add(tuple(point))
			trees.append(a)
		t1 = -1
		t2 = -1
		tot = 0
		for e in sorted(edges):
			(l, p1, p2) = e
			for (i, tree) in enumerate(trees):
				if p1 in tree:
					t1 = i
					break
			for (i, tree) in enumerate(trees):
				if p2 in tree:
					t2 = i
					break
			if t1 != t2:
				tot += l
				trees[t1].update(trees[t2])
				del trees[t2]
		return tot


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		l = len(points)
		c = collections.defaultdict(list)
		for i in range(l - 1):
			for j in range(i + 1, l):
				d = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				c[d].append((i, j))
		tocons = list(sorted(c.keys()))

		def isCyclicUtil(v, visited, parent, graph):
			visited[v] = True
			for i in graph[v]:
				if visited[i] == False:
					if isCyclicUtil(i, visited, v, graph):
						return True
				elif parent != i:
					return True
			return False

		def checkloop(y, connected, edges):
			if y[0] not in connected or y[1] not in connected:
				return True
			root = y[0]
			visited = [False] * l
			graph = collections.defaultdict(list)
			graph[y[0]] = [y[1]]
			graph[y[1]] = [y[0]]
			for x in edges:
				graph[x[0]].append(x[1])
				graph[x[1]].append(x[0])
			for (i, x) in enumerate(connected):
				if visited[x] == False:
					if isCyclicUtil(x, visited, -1, graph) == True:
						return False
			return True
		edges = []
		count = 0
		cost = 0
		connected = set()
		for x in tocons:
			for y in c[x]:
				if checkloop(y, connected, edges):
					count += 1
					cost += x
					connected.add(y[0])
					connected.add(y[1])
					edges.append(y)
				if count == l - 1:
					return cost
		return 0


class Solution:

	def minCostConnectPoints(self, points) -> int:
		p_set = [i for i in range(len(points))]

		def father(i):
			while p_set[i] != i:
				i = p_set[i]
			return i
		if len(points) == 1:
			return 0
		edge = {}
		edgelist = []
		res = 0
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				le = 0
				le += abs(points[i][1] - points[j][1])
				le += abs(points[i][0] - points[j][0])
				if le in edge:
					edge[le].append((i, j))
				else:
					edge[le] = [(i, j)]
					edgelist.append(le)
		edgelist.sort()
		(i, j) = edge[edgelist[0]][0]
		res += edgelist[0]
		p_set[j] = i
		for key in edgelist:
			for (i, j) in edge[key]:
				fi = father(i)
				fj = father(j)
				if fj != fi:
					p_set[fj] = fi
					res += key
		return res


class UnionFind:

	def __init__(self, n):
		self.parent = [i for i in range(n)]
		self.height = [0 for i in range(n)]

	def find(self, x):
		if self.parent[x] == x:
			return x
		result = self.find(self.parent[x])
		self.parent[x] = result
		return result

	def merge(self, x, y):
		rx = self.find(x)
		ry = self.find(y)
		if self.height[rx] > self.height[ry]:
			self.parent[ry] = rx
		elif self.height[rx] < self.height[ry]:
			self.parent[rx] = ry
		else:
			self.parent[rx] = ry
			self.height[rx] += 1

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		edges = []
		for i in range(n):
			for j in range(i + 1, n):
				heappush(edges, (abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1]), i, j))
		uf = UnionFind(n)
		ans = 0
		while edges:
			(cost, va, vb) = heappop(edges)
			if uf.find(va) == uf.find(vb):
				pass
			else:
				uf.merge(va, vb)
				ans += cost
		return ans


from collections import Counter

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		points = [tuple(it) for it in points]
		ds = []
		for (i1, p1) in enumerate(points):
			for p2 in points[i1 + 1:]:
				if p1 == p2:
					continue
				dist = abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
				ds.append((dist, (p1, p2)))
		ds.sort()
		ps = [set([it]) for it in points]
		total = 0
		for (cost, (p1, p2)) in ds:
			s1 = [it for it in ps if p1 in it][0]
			s2 = [it for it in ps if p2 in it][0]
			if s1 is s2:
				continue
			total += cost
			s1 |= s2
			ps.remove(s2)
		return total


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) <= 1:
			return 0
		visited = set()
		adj_list = defaultdict(list)
		cost = 0
		pq = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				first = points[i]
				second = points[j]
				adj_list[tuple(first)].append([abs(first[0] - second[0]) + abs(first[1] - second[1]), second])
				adj_list[tuple(second)].append([abs(first[0] - second[0]) + abs(first[1] - second[1]), first])
		pq = pq + adj_list[list(adj_list.keys())[0]]
		heapq.heapify(pq)
		visited.add(tuple(list(adj_list.keys())[0]))
		while len(visited) < len(adj_list):
			curr = heapq.heappop(pq)
			if tuple(curr[1]) not in visited:
				visited.add(tuple(curr[1]))
				for edge in adj_list[tuple(curr[1])]:
					heapq.heappush(pq, edge)
				cost += curr[0]
		return cost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		if n == 1:
			return 0
		parents = list(range(n))

		def find(i):
			if parents[i] != i:
				parents[i] = find(parents[i])
			return parents[i]

		def union(i, j):
			p_i = find(i)
			p_j = find(j)
			if p_i != p_j:
				if p_i > p_j:
					parents[p_j] = p_i
				else:
					parents[p_i] = p_j
		heap = []
		for i in range(n):
			for j in range(i + 1, n):
				heapq.heappush(heap, (self.distance(points[i], points[j]), i, j))
		res = 0
		while heap:
			(dist, i, j) = heapq.heappop(heap)
			if find(i) == find(j):
				continue
			union(i, j)
			res += dist
		return res

	def distance(self, p1, p2):
		return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])


import heapq

class DSU:

	def __init__(self, n):
		self.p = list(range(n))

	def find(self, x):
		if self.p[x] != x:
			self.p[x] = self.find(self.p[x])
		return self.p[x]

	def union(self, x, y):
		p_x = self.find(x)
		p_y = self.find(y)
		if p_x != p_y:
			self.p[p_x] = p_y
			return True
		return False

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		if n < 2:
			return 0

		def dist(p1, p2):
			return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		edges = []
		for i in range(n):
			for j in range(i + 1, n):
				edges.append([dist(points[i], points[j]), i, j])
		heapq.heapify(edges)
		dsu = DSU(n)
		res = 0
		while edges:
			(cost, p1, p2) = heapq.heappop(edges)
			if dsu.union(p1, p2):
				res += cost
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		N = len(points)
		graph = defaultdict(list)
		for i in range(N):
			for j in range(N):
				if i != j:
					(x1, y1) = points[i]
					(x2, y2) = points[j]
					dist = abs(x1 - x2) + abs(y1 - y2)
					graph[i].append((j, dist))
					graph[j].append((i, dist))
		pq = [(0, 0)]
		visited = set()
		cost = 0
		while len(visited) < N:
			(dist, node) = heappop(pq)
			if node not in visited:
				visited.add(node)
				cost += dist
				for (adj, dist) in graph[node]:
					if adj not in visited:
						heappush(pq, (dist, adj))
		return cost


class UF:

	def __init__(self, n):
		self.parents = [i for i in range(n)]

	def find(self, x):
		if x != self.parents[x]:
			self.parents[x] = self.find(self.parents[x])
		return self.parents[x]

	def union(self, x, y):
		parent_x = self.find(x)
		parent_y = self.find(y)
		self.parents[parent_y] = parent_x

	def connected(self, y, x):
		return self.find(y) == self.find(x)

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def calculate_distance(x1, y1, x2, y2):
			return abs(x1 - x2) + abs(y1 - y2)
		n = len(points)
		uf = UF(n)
		res = 0
		p = []
		for i in range(n):
			for j in range(n):
				if i != j:
					p.append((i, j, calculate_distance(points[i][0], points[i][1], points[j][0], points[j][1])))
		p.sort(key=lambda x: x[2])
		for (x, y, dist) in p:
			if not uf.connected(x, y):
				uf.union(x, y)
				res += dist
		return res


class UnionFind:

	def __init__(self, N):
		self.par = list(range(N))
		self.sz = [1] * N

	def find(self, x):
		if self.par[x] != x:
			self.par[x] = self.find(self.par[x])
		return self.par[x]

	def union(self, x, y):
		(xr, yr) = (self.find(x), self.find(y))
		if xr == yr:
			return False
		if self.sz[xr] < self.sz[yr]:
			(xr, yr) = (yr, xr)
		self.par[yr] = xr
		self.sz[xr] += self.sz[yr]
		self.sz[yr] = self.sz[xr]
		return True

	def size(self, x):
		return self.sz[self.find(x)]

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		if n <= 1:
			return 0
		distances = []
		db = dict()
		for i in range(n):
			(x1, y1) = points[i]
			for j in range(i + 1, n):
				(x2, y2) = points[j]
				dis = abs(x1 - x2) + abs(y1 - y2)
				distances.append(dis)
				if dis not in db:
					db[dis] = []
				db[dis].append((i, j))
		heapq.heapify(distances)
		nodes = UnionFind(n)
		ret = []
		cost = 0
		while distances:
			dis = heapq.heappop(distances)
			(p1, p2) = db[dis].pop()
			if nodes.union(p1, p2):
				cost += dis
		return cost


class UF:

	@staticmethod
	def init(n):
		return [i for i in range(n)]

	@staticmethod
	def find(parents, i):
		if parents[i] != i:
			parents[i] = UF.find(parents, parents[i])
		return parents[i]

	@staticmethod
	def union(parents, i, j):
		parents[UF.find(parents, i)] = UF.find(parents, j)

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		distances = []
		n = len(points)
		for i in range(n):
			(r1, c1) = points[i]
			for j in range(i + 1, n):
				(r2, c2) = points[j]
				distances.append([abs(r1 - r2) + abs(c1 - c2), i, j])
		distances.sort()
		res = 0
		parents = UF.init(n)
		for (c, i, j) in distances:
			if UF.find(parents, i) != UF.find(parents, j):
				UF.union(parents, i, j)
				res += c
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		if len(points) == 1:
			return 0
		visited = [0] * len(points)
		q = []
		start = 0
		for i in range(1, len(points)):
			dist = abs(points[i][0] - points[0][0]) + abs(points[i][1] - points[0][1])
			q.append([dist, i])
		heapq.heapify(q)
		visited[0] = 1
		cost = 0
		count = 1
		while True:
			x = heapq.heappop(q)
			if visited[x[1]] == 0:
				cost = cost + x[0]
				visited[x[1]] = 1
				count = count + 1
			if count == len(points):
				return cost
			for i in range(len(points)):
				if visited[i] == 0:
					dist = abs(points[i][0] - points[x[1]][0]) + abs(points[i][1] - points[x[1]][1])
					heapq.heappush(q, [dist, i])


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def distance(p1, p2):
			return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1])
		edges = []
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				if i == j:
					continue
				edges.append([distance(points[i], points[j]), i, j])
		edges.sort()
		fathers = {p: p for p in range(len(points))}

		def find_father(p):
			while fathers[p] != fathers[fathers[p]]:
				fathers[p] = find_father(fathers[p])
			return fathers[p]
		result = 0
		for (d, p1, p2) in edges:
			if find_father(p1) == find_father(p2):
				continue
			fathers[find_father(p2)] = find_father(p1)
			result += d
		return result


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		heap = [(0, -1, 0)]
		seen = set()
		seen.add(-1)
		heapq.heapify(heap)
		cost = 0

		def calc_dist(a, b):
			return abs(a[0] - b[0]) + abs(a[1] - b[1])
		while len(seen) <= len(points):
			(c, a, b) = heapq.heappop(heap)
			if b in seen:
				continue
			seen.add(b)
			cost += c
			for j in range(len(points)):
				if j not in seen:
					heapq.heappush(heap, (calc_dist(points[b], points[j]), b, j))
		return cost


class Solution:

	def find(self, uf, node):
		if node not in uf:
			uf[node] = node
		while node != uf[node]:
			node = uf[node]
		return node

	def union(self, uf, node1, node2):
		uf[self.find(uf, node1)] = self.find(uf, node2)

	def distance(self, point1, point2):
		return abs(point1[0] - point2[0]) + abs(point1[1] - point2[1])

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		cost = 0
		edges = []
		uf = {}
		for i in range(len(points)):
			for j in range(i + 1, len(points)):
				edges.append([i, j, self.distance(points[i], points[j])])
		edges = sorted(edges, key=lambda x: x[2])
		for edge in edges:
			point1 = edge[0]
			point2 = edge[1]
			edgeCost = edge[2]
			if self.find(uf, point1) != self.find(uf, point2):
				self.union(uf, point1, point2)
				cost += edgeCost
		return cost


class UnionFind:

	def __init__(self, V):
		self.parent = [-1] * V

	def union(self, v1, v2):
		r1 = self.find(v1)
		r2 = self.find(v2)
		if r1 == r2:
			return
		s1 = self.size(r1)
		s2 = self.size(r2)
		if s1 <= s2:
			self.parent[r1] = r2
			self.parent[r2] -= s1
		else:
			self.parent[r2] = r1
			self.parent[r1] -= s2

	def find(self, v):
		r = v
		while self.parent[r] >= 0:
			r = self.parent[r]
		while v != r:
			new_v = self.parent[v]
			self.parent[v] = r
			v = new_v
		return r

	def size(self, v):
		r = self.find(v)
		s = -self.parent[r]
		return s

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		n = len(points)
		edges = []
		for u in range(n):
			for v in range(u + 1, n):
				dist = abs(points[u][0] - points[v][0]) + abs(points[u][1] - points[v][1])
				edges.append([dist, u, v])
		res = 0
		uf = UnionFind(n)
		for e in sorted(edges):
			if uf.find(e[1]) != uf.find(e[2]):
				res += e[0]
				uf.union(e[1], e[2])
		return res


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		import heapq
		n = len(points)
		pq = [(0, 0)]
		seen = [False] * n
		totalCost = 0
		while pq:
			(cost, currPoint) = heapq.heappop(pq)
			if seen[currPoint]:
				continue
			seen[currPoint] = True
			totalCost += cost
			(x1, y1) = points[currPoint]
			for i in range(n):
				if i != currPoint and (not seen[i]):
					(x2, y2) = points[i]
					d = abs(x2 - x1) + abs(y2 - y1)
					heapq.heappush(pq, (d, i))
		return totalCost


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:

		def find(u):
			if u != group[u]:
				group[u] = find(group[u])
			return group[u]

		def unite(u, v):
			(u, v) = (find(u), find(v))
			if u == v:
				return False
			if sz[u] < sz[v]:
				(u, v) = (v, u)
			group[v] = u
			sz[u] += sz[v]
			return True
		edges = []
		for i in range(len(points)):
			for j in range(len(points)):
				dist = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				edges.append((dist, i, j))
		edges.sort()
		ans = 0
		group = [i for i in range(len(points))]
		sz = [1 for i in range(len(points))]
		for (e, u, v) in edges:
			if unite(u, v):
				ans += e
		return ans


class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		graph = collections.defaultdict(list)
		for i in range(len(points)):
			(x0, y0) = points[i]
			for j in range(i + 1, len(points)):
				(x1, y1) = points[j]
				dist = abs(x1 - x0) + abs(y1 - y0)
				graph[i] += [(j, dist)]
				graph[j] += [(i, dist)]
		(res, visited, heap) = (0, set(), [(0, 0)])
		while heap and len(visited) <= len(points):
			(dist, node) = heapq.heappop(heap)
			if node in visited:
				continue
			res += dist
			visited.add(node)
			for (n, d) in graph[node]:
				if n in visited:
					continue
				heapq.heappush(heap, (d, n))
		return res


class Union:

	def __init__(self):
		self.parent = {}
		self.rank = {}
		self.count = 0

	def add(self, idx):
		if idx not in self.parent:
			self.parent[idx] = idx
			self.rank[idx] = 1
			self.count += 1

	def find(self, idx):
		if self.parent[idx] != idx:
			self.parent[idx] = self.find(self.parent[idx])
		return self.parent[idx]

	def unite(self, p, q):
		(i, j) = (self.find(p), self.find(q))
		if i == j:
			return True
		if self.rank[i] > self.rank[j]:
			(i, j) = (j, i)
		self.parent[i] = j
		self.rank[j] += self.rank[i]
		self.count -= 1
		return False

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		costs = []
		point = Union()
		for i in range(len(points) - 1):
			for j in range(i + 1, len(points)):
				cost = abs(points[i][0] - points[j][0]) + abs(points[i][1] - points[j][1])
				costs.append([i, j, cost])
		costs.sort(key=lambda x: x[2])
		res = 0
		for (i, j, c) in costs:
			point.add(i)
			point.add(j)
			if not point.unite(i, j):
				res += c
		return res


class Solution:

	def minCostConnectPoints(self, a: List[List[int]]) -> int:
		n = len(a)
		g = defaultdict(set)

		@lru_cache(None)
		def dist(x1, y1, x2, y2):
			return abs(x1 - x2) + abs(y1 - y2)
		for i in range(n):
			for j in range(i + 1, n):
				(x1, y1) = a[i]
				(x2, y2) = a[j]
				w = dist(x1, y1, x2, y2)
				g[x1, y1].add((w, x2, y2))
				g[x2, y2].add((w, x1, y1))
		q = [(0, (a[0][0], a[0][-1]))]
		visited = set()
		total = ct = 0
		while q:
			(c, (x1, y1)) = heapq.heappop(q)
			if (x1, y1) in visited:
				continue
			visited.add((x1, y1))
			total += c
			ct += 1
			for (w, x2, y2) in g[x1, y1]:
				heapq.heappush(q, (w, (x2, y2)))
			if ct >= n:
				break
		return total


class UF:

	def __init__(self, n):
		self.parents = [i for i in range(n)]

	def find(self, x):
		if self.parents[x] != x:
			self.parents[x] = self.find(self.parents[x])
		return self.parents[x]

	def union(self, x, y):
		(px, py) = (self.find(x), self.find(y))
		if px == py:
			return False
		self.parents[py] = px
		return True

class Solution:

	def minCostConnectPoints(self, points: List[List[int]]) -> int:
		distances = []
		for (i, [xi, yi]) in enumerate(points):
			for j in range(i + 1, len(points)):
				(xj, yj) = points[j]
				d = abs(xi - xj) + abs(yi - yj)
				distances.append([d, i, j])
		distances.sort()
		uf = UF(len(points))
		ans = 0
		for (d, i, j) in distances:
			if uf.union(i, j):
				ans += d
		return ans