#include<tuple>
#include<stdio.h>
#include<iostream>
#include<vector>
#include<algorithm>
#include<string>
#include<string.h>

#ifdef LOCAL
#define eprintf(...) fprintf(stderr, __VA_ARGS__)
#else
#define NDEBUG
#define eprintf(...) do {} while (0)
#endif
#include<cassert>

using namespace std;

typedef long long LL;
typedef vector<int> VI;

#define REP(i,n) for(int i=0, i##_len=(n); i<i##_len; ++i)
#define EACH(i,c) for(__typeof((c).begin()) i=(c).begin(),i##_end=(c).end();i!=i##_end;++i)

template<class T> inline void amin(T &x, const T &y) { if (y<x) x=y; }
template<class T> inline void amax(T &x, const T &y) { if (x<y) x=y; }
template<class Iter> void rprintf(const char *fmt, Iter begin, Iter end) {
    for (bool sp=0; begin!=end; ++begin) { if (sp) putchar(' '); else sp = true; printf(fmt, *begin); }
    putchar('\n');
}

struct UnionFind {
    int n, cc, *u;
    UnionFind() : n(0), cc(0), u(NULL) {}
    UnionFind(int n_) : n(n_), cc(n_) {
	u = new int[n_];
	memset(u, -1, sizeof (int) * n);
    }
    UnionFind(const UnionFind &y) : n(y.n), cc(y.cc) {
	u = new int[y.n];
	memcpy(u, y.u, sizeof (int) * n);
    }
    ~UnionFind() {
	delete[] u; u = NULL;
	n = cc = 0;
    }
    friend void swap(UnionFind &x, UnionFind &y) {
	swap(x.n, y.n); swap(x.cc, y.cc); swap(x.u, y.u);
    }
    UnionFind& operator=(UnionFind y) { 
	swap(*this, y);
	return *this;
    }
    int root(int x) {
	int y = x, t;
	while (u[y] >= 0) y = u[y];
	while (x != y) { t = u[x]; u[x] = y; x = t; }
	return y;
    }
    bool link(int x, int y) {
	x = root(x); y = root(y);
	if (x == y) return false;
	if (u[y] < u[x]) swap(x, y);
	u[x] += u[y]; u[y] = x; cc--;
	return true;
    }
    bool same(int x, int y) { return root(x) == root(y); }
    int size(int x) { return -u[root(x)]; }
    int count() { return cc; }
};
const int MAXN = 200011;
int N;
LL X[MAXN];
vector<pair<int, LL> > G[MAXN];
int par[MAXN];


struct Data {
    LL cst;
    int color;
    int id;
    bool operator<(const Data &y) const {
	return cst != y.cst? cst < y.cst: id < y.id;
    }
};
Data D[MAXN][2];

void update(int v, Data g) {
    if (g < D[v][1]) swap(D[v][1], g);
    if (D[v][1] < D[v][0]) swap(D[v][0], D[v][1]);
    if (D[v][0].color == D[v][1].color) swap(D[v][1], g);
}

void MAIN() {
    scanf("%d", &N);
    REP (i, N) scanf("%lld", X+i);
    REP (i, N-1) {
	int x, y, c;
	scanf("%d%d%d", &x, &y, &c);
	x--; y--;
	G[x].emplace_back(y, c);
	G[y].emplace_back(x, c);
    }

    VI ord;
    ord.reserve(N);
    ord.push_back(0);
    REP (i_, N) {
	int v = ord[i_];
	EACH (e, G[v]) if (e->first != par[v]) {
	    ord.push_back(e->first);
	    par[e->first] = v;
	}
    }
    
    LL ans = 0;
    UnionFind U(N);
    while (U.count() > 1) {
	REP (i_, N) {
	    int v = ord[N-1-i_];
	    D[v][0] = D[v][1] = { X[v], U.root(v), v };

	    EACH (e, G[v]) if (e->first != par[v]) {
		REP (t, 2) {
		    Data g = D[e->first][t];
		    g.cst += e->second;
		    update(v, g);
		}
	    }
	}

	REP (i_, N) {
	    int v = ord[i_];
	    EACH (e, G[v]) if (e->first != par[v]) {
		REP (t, 2) {
		    Data g = D[v][t];
		    g.cst += e->second;
		    update(e->first, g);
		}
	    }
	}

	// color, cst, ver, ver;
	using Tuple = tuple<int, LL, int, int>;
	vector<Tuple> Z;
	REP (v, N) {
	    int r = U.root(v);
	    if (D[v][0].color != r) {
		Z.emplace_back(r, X[v] + D[v][0].cst, v, D[v][0].id);
	    } else {
		Z.emplace_back(r, X[v] + D[v][1].cst, v, D[v][1].id);
	    }
	}

	sort(Z.begin(), Z.end());
	int len = 0;
	REP (i, N) if (i==0 || get<0>(Z[i-1]) != get<0>(Z[i])) Z[len++] = Z[i];
	Z.resize(len);
	EACH (e, Z) {
	    get<0>(*e) = 0;
	    if (get<2>(*e) > get<3>(*e)) swap(get<2>(*e), get<3>(*e));
	}
	sort(Z.begin(), Z.end());
	REP (i, Z.size()) if (i == 0 || Z[i-1] != Z[i]) {
	    int dummy;
	    int x, y;
	    LL cst;
	    tie(dummy, cst, x, y) = Z[i];
	    ans += cst;
	    U.link(x, y);
	}
    }

    printf("%lld\n", ans);
}

int main() {
    int TC = 1;
//    scanf("%d", &TC);
    REP (tc, TC) MAIN();
    return 0;
}



Measured memory_bytes: 38904