
AC
- 最小生成树,建边的时候不需要N2,首先N个点需要N-1条边,每个顶点都会用到,也会有一些顶点重复。我们让重复的点为权值最小的点,就可以保证生成树最小
- 将特殊边加到边集里,跑一边Kruskal
#include <bits/stdc++.h>
#define P pair<int, int>
#define lowbit(x) (x & -x)
#define mem(a, b) memset(a, b, sizeof(a))
#define REP(i, n) for (int i = 1; i <= (n); ++i)
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define N 200006
#define LL long long
using namespace std;
struct ac{
LL u, v, d;
}g[N*2];
LL a[N];
int fa[N];
int find(int x) {
return x == fa[x] ? x : fa[x] = find(fa[x]);
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
int n, m;
while (scanf("%d %d", &n, &m) != EOF) {
int pos = 1;
REP (i, n) {
scanf("%lld", &a[i]);
if (a[i] < a[pos]) pos = i;
}
int len = 0;
REP (i, n) {
if (i == pos) continue;
g[len].u = pos;
g[len].v = i;
g[len].d = a[pos] + a[i];
len++;
}
rep (i, m) {
scanf("%lld %lld %lld", &g[len].u, &g[len].v, &g[len].d);
++len;
}
sort(g, g + len, [&](const ac &x, const ac &y){
return x.d < y.d;
});
REP (i, n) fa[i] = i;
LL u, v, d, ans = 0, cnt = 0;
rep (i, len) {
u = g[i].u;
v = g[i].v;
d = g[i].d;
if (find(u) != find(v)) {
fa[find(u)] = find(v);
ans += d;
if (++cnt == n-1) break;
}
}
printf("%lld\n", ans);
}
return 0;
}