You are given an undirected graph consisting of $n$ vertices. A number is written on each vertex; the number on vertex $i$ is $a_i$. Initially there are no edges in the graph.

You may add some edges to this graph, but you have to pay for them. The cost of adding an edge between vertices $x$ and $y$ is $a_x + a_y$ coins. There are also $m$ special offers, each of them is denoted by three numbers $x$, $y$ and $w$, and means that you can add an edge connecting vertices $x$ and $y$ and pay $w$ coins for it. You don't have to use special offers: if there is a pair of vertices $x$ and $y$ that has a special offer associated with it, you still may connect these two vertices paying $a_x + a_y$ coins for it.

What is the minimum number of coins you have to spend to make the graph connected? Recall that a graph is connected if it's possible to get from any vertex to any other vertex using only the edges belonging to this graph.


-----Input-----

The first line contains two integers $n$ and $m$ ($1 \le n \le 2 \cdot 10^5$, $0 \le m \le 2 \cdot 10^5$) — the number of vertices in the graph and the number of special offers, respectively.

The second line contains $n$ integers $a_1, a_2, \dots, a_n$ ($1 \le a_i \le 10^{12}$) — the numbers written on the vertices.

Then $m$ lines follow, each containing three integers $x$, $y$ and $w$ ($1 \le x, y \le n$, $1 \le w \le 10^{12}$, $x \ne y$) denoting a special offer: you may add an edge connecting vertex $x$ and vertex $y$, and this edge will cost $w$ coins.


-----Output-----

Print one integer — the minimum number of coins you have to pay to make the graph connected.


-----Examples-----
Input
3 2
1 3 3
2 3 5
2 1 1

Output
5

Input
4 0
1 3 3 7

Output
16

Input
5 4
1 2 3 4 5
1 2 8
1 3 10
1 4 7
1 5 15

Output
18



-----Note-----

In the first example it is possible to connect $1$ to $2$ using special offer $2$, and then $1$ to $3$ without using any offers.

In next two examples the optimal answer may be achieved without using special offers.

Difficulty: HARD
Tags: Spanning trees

Graph algorithms

Greedy algorithms
Skill types: Greedy algorithms

Starter code:

Solutions:
(n, m) = map(int, input().split())
a = list(map(int, input().split()))
e = []
for _ in range(m):
	(u, v, w) = map(int, input().split())
	e.append((u - 1, v - 1, w))
a = sorted(zip(a, range(n)), key=lambda x: x[0])
for i in range(1, n):
	e.append((a[0][1], a[i][1], a[0][0] + a[i][0]))
fa = list(range(n))
rk = [0] * n

def find(x):
	while fa[x] != x:
		fa[x] = fa[fa[x]]
		x = fa[x]
	return x

def unite(u, v):
	(u, v) = map(find, (u, v))
	if u == v:
		return False
	if rk[u] < rk[v]:
		(u, v) = (v, u)
	fa[v] = u
	if rk[u] == rk[v]:
		rk[u] += 1
	return True
e.sort(key=lambda x: x[2])
ans = 0
cnt = 1
for ee in e:
	if cnt == n:
		break
	if unite(ee[0], ee[1]):
		ans += ee[2]
		cnt += 1
print(ans)


import sys
from io import StringIO

def main():

	def find_set(v):
		tmp = []
		while v != parent[v]:
			tmp.append(v)
			v = parent[v]
		for i in tmp:
			parent[i] = v
		return v
	sys.stdin = StringIO(sys.stdin.read())
	input = lambda : sys.stdin.readline().rstrip('\r\n')
	(n, m) = list(map(int, input().split(' ')))
	a = list(map(int, input().split(' ')))
	edges = []
	for _ in range(m):
		(x, y, w) = list(map(int, input().split(' ')))
		edges.append((x - 1, y - 1, w))
	min_val = min(a)
	min_ind = a.index(min_val)
	for i in range(n):
		edges.append((min_ind, i, min_val + a[i]))
	(parent, rank) = (list(range(n)), [0] * n)
	cost = 0
	for edge in sorted(edges, key=lambda edge: edge[2]):
		(find_u, find_v) = (find_set(edge[0]), find_set(edge[1]))
		if find_u != find_v:
			cost += edge[2]
			if rank[find_u] < rank[find_v]:
				(find_v, find_u) = (find_u, find_v)
			elif rank[find_u] == rank[find_v]:
				rank[find_u] += 1
			parent[find_v] = find_u
	print(cost)
main()


import sys
from io import StringIO
(n, spec) = map(int, input().split())
p = list(range(n + 1))

def isconnected(x, y):
	return find(x) == find(y)

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

def connect(x, y):
	global p
	p[find(x)] = find(y)
e = []
sys.stdin = StringIO(sys.stdin.read())
input = lambda : sys.stdin.readline().strip()
a = list(zip(map(int, input().split()), range(1, n + 1)))
m = min(a)
for i in a:
	if i[1] != m[1]:
		e.append((i[1], m[1], i[0] + m[0]))
for i in range(spec):
	e.append(tuple(map(int, input().split())))
e.sort(key=lambda x: x[2])
count = 0
ans = 0
for x in e:
	if not isconnected(x[0], x[1]):
		count += 1
		connect(x[0], x[1])
		ans += x[2]
	if count == n - 1:
		break
print(ans)


def main():
	(n, m) = map(int, input().split())
	a = list(map(int, input().split()))
	b = [tuple(map(int, input().split())) for i in range(m)]
	rt = a.index(min(a))
	e = [(a[i] + a[rt], rt, i) for i in range(n) if i != rt] + [(w, u - 1, v - 1) for (u, v, w) in b]
	e.sort()
	p = [i for i in range(n)]
	r = [0] * n

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

	def check_n_unite(x, y):
		(x, y) = (find(x), find(y))
		if x == y:
			return 0
		if r[x] < r[y]:
			(x, y) = (y, x)
		p[y] = x
		if r[x] == r[y]:
			r[x] += 1
		return 1
	ans = 0
	for (w, u, v) in e:
		if check_n_unite(u, v):
			ans += w
	print(ans)
main()


def read_nums():
	return [int(x) for x in input().split()]

class UnionFind:

	def __init__(self, size):
		self._parents = list(range(size))
		self._sizes = [1 for _ in range(size)]

	def _root(self, a):
		while a != self._parents[a]:
			self._parents[a] = self._parents[self._parents[a]]
			a = self._parents[a]
		return a

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

	def union(self, a, b):
		(a, b) = (self._root(a), self._root(b))
		if self._sizes[a] < self._sizes[b]:
			self._parents[a] = b
			self._sizes[b] += self._sizes[a]
		else:
			self._parents[b] = a
			self._sizes[a] += self._sizes[b]

def count_result(num_vertex, edges):
	uf = UnionFind(num_vertex)
	res = 0
	for (start, end, cost) in edges:
		if uf.find(start, end):
			continue
		else:
			uf.union(start, end)
			res += cost
	return res

def main():
	(n, m) = read_nums()
	vertex_nums = read_nums()
	edges = []
	for i in range(m):
		nums = read_nums()
		nums[0] -= 1
		nums[1] -= 1
		edges.append(nums)
	min_index = min([x for x in zip(vertex_nums, range(n))], key=lambda x: x[0])[1]
	for i in range(n):
		if i != min_index:
			edges.append((min_index, i, vertex_nums[min_index] + vertex_nums[i]))
	edges = sorted(edges, key=lambda x: x[2])
	print(count_result(n, edges))
main()


import sys, os
from math import sqrt, gcd, ceil, log, floor
from math import factorial as fact
from bisect import bisect, bisect_left
from collections import defaultdict, Counter, deque
from heapq import heapify, heappush, heappop
from itertools import permutations
input = sys.stdin.readline
read = lambda : list(map(int, input().strip().split()))
MOD = 10 ** 9 + 7

def main():

	def find(x):
		while par[x] != x:
			par[x] = par[par[x]]
			x = par[x]
		return x
	(n, m) = read()
	cost = [10 ** 12 + 1] + read()
	mn = 10 ** 12 * 2
	mnind = 0
	for i in range(1, n + 1):
		if mn > cost[i]:
			mn = cost[i]
			mnind = i
	arr = [[mnind, i, cost[i] + mn] for i in range(1, n + 1) if i != mnind]
	a = [read() for i in range(m)]
	arr += a
	arr.sort(key=lambda x: x[2])
	par = [i for i in range(n + 1)]
	ans = 0
	for (a, b, cost) in arr:
		f_a = find(a)
		f_b = find(b)
		if f_a != f_b:
			par[f_a] = f_b
			ans += cost
	print(ans)
main()


class UnionFind:

	def __init__(self, n):
		self.par = [-1] * n
		self.rank = [0] * n

	def Find(self, x):
		if self.par[x] < 0:
			return x
		else:
			self.par[x] = self.Find(self.par[x])
			return self.par[x]

	def Unite(self, x, y):
		x = self.Find(x)
		y = self.Find(y)
		if x != y:
			if self.rank[x] < self.rank[y]:
				self.par[y] += self.par[x]
				self.par[x] = y
			else:
				self.par[x] += self.par[y]
				self.par[y] = x
				if self.rank[x] == self.rank[y]:
					self.rank[x] += 1

	def Same(self, x, y):
		return self.Find(x) == self.Find(y)

	def Size(self, x):
		return -self.par[self.Find(x)]
import sys
import io, os
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline
(n, m) = map(int, input().split())
A = list(map(int, input().split()))
w0 = min(A)
v0 = A.index(w0)
edge = [(v0, v1, w0 + w1) for (v1, w1) in enumerate(A) if v1 != v0]
for i in range(m):
	(x, y, w) = map(int, input().split())
	(x, y) = (x - 1, y - 1)
	edge.append((x, y, w))
edge.sort(key=lambda x: x[2])
uf = UnionFind(n)
ans = 0
for (u, v, w) in edge:
	if not uf.Same(u, v):
		ans += w
		uf.Unite(u, v)
print(ans)


import sys
input = sys.stdin.readline
(n, m) = map(int, input().split())
A = list(map(int, input().split()))
SP = [list(map(int, input().split())) for i in range(m)]
MIN = min(A)
x = A.index(MIN)
EDGE_x = [[x + 1, i + 1, A[x] + A[i]] for i in range(n) if x != i]
EDGE = EDGE_x + SP
EDGE.sort(key=lambda x: x[2])
Group = [i for i in range(n + 1)]

def find(x):
	while Group[x] != x:
		x = Group[x]
	return x

def Union(x, y):
	if find(x) != find(y):
		Group[find(y)] = Group[find(x)] = min(find(y), find(x))
ANS = 0
for (i, j, x) in EDGE:
	if find(i) != find(j):
		ANS += x
		Union(i, j)
print(ANS)


from sys import stdin, stdout
input = stdin.readline
import gc, os
from os import _exit
gc.disable()

def put():
	return map(int, input().split())

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

def union(i, j):
	if rank[i] > rank[j]:
		(i, j) = (j, i)
	p[i] = j
	if rank[i] == rank[j]:
		rank[j] += 1
(n, m) = put()
l = list(put())
edge = []
minw = min(l)
mini = l.index(minw)
for _ in range(m):
	(x, y, w) = put()
	(x, y) = (x - 1, y - 1)
	edge.append((w, x, y))
for i in range(n):
	if i != mini:
		w = l[i] + minw
		edge.append((w, mini, i))
edge.sort()
p = [i for i in range(n)]
rank = [0] * n
ans = 0
for (w, x, y) in edge:
	x = find(x)
	y = find(y)
	if x != y:
		union(x, y)
		ans += w
stdout.write(str(ans))
stdout.flush()
_exit(0)