Problem:
Score : 1900 points

Problem Statement

Ringo has a tree with N vertices.
The i-th of the N-1 edges in this tree connects Vertex A_i and Vertex B_i and has a weight of C_i.
Additionally, Vertex i has a weight of X_i.

Here, we define f(u,v) as the distance between Vertex u and Vertex v, plus X_u + X_v.

We will consider a complete graph G with N vertices.
The cost of its edge that connects Vertex u and Vertex v is f(u,v).
Find the minimum spanning tree of G.

Constraints

2 \leq N \leq 200,000

1 \leq X_i \leq 10^9

1 \leq A_i,B_i \leq N

1 \leq C_i \leq 10^9

The given graph is a tree.

All input values are integers.

Input

Input is given from Standard Input in the following format:

N
X_1 X_2 ... X_N
A_1 B_1 C_1
A_2 B_2 C_2
:
A_{N-1} B_{N-1} C_{N-1}

Output

Print the cost of the minimum spanning tree of G.

Sample Input 1

4
1 3 5 1
1 2 1
2 3 2
3 4 3

Sample Output 1

22

We connect the following pairs: Vertex 1 and 2, Vertex 1 and 4, Vertex 3 and 4. The costs are 5, 8 and 9, respectively, for a total of 22.

Sample Input 2

6
44 23 31 29 32 15
1 2 10
1 3 12
1 4 16
4 5 8
4 6 15

Sample Output 2

359

Sample Input 3

2
1000000000 1000000000
2 1 1000000000

Sample Output 3

3000000000

Solution in C++14 (GCC 5.4.1) (judge verdict: Runtime Error)

/*input
2
1000000000 1000000000
2 1 1000000000
*/
#include <bits/stdc++.h>
using namespace std;

const int N = 200005;
const long long inf = 1e16;

int read() {
	int x = 0, c = getchar();
	for(; !(c > 47 && c < 58); c = getchar());
	for(; (c > 47 && c < 58); c = getchar()) x = x * 10 + c - 48;
	return x;
}

struct Edge {
	int u, v, w;
	Edge(int _u = 0, int _v = 0, int _w = 0):
		u(_u), v(_v), w(_w) {}

	int to(int x) {
		return u + v - x;
	}
} edge[N << 1];

vector<Edge> binTree;
vector<int> G[N << 1]; // edge id of the tree

int n;
int value[N];

void pre_dfs(int u, int p) {
	for(int i = 0; i < (int)G[u].size(); ++ i) {
		int id = G[u][i], v = edge[id].to(u);
		if(v == p) {
			swap(G[u][i], G[u].back()), G[u].pop_back();
			-- i; continue;
		}
		pre_dfs(v, u);
	}
}

// start of the centroid
int del[N << 1];
int partOfMst[N];

typedef pair<long long, int> uwu;
priority_queue<uwu, vector<uwu>, greater<uwu> > candidates;

// helper centroid variables
vector<int> rootsOf[N];
vector<uwu> nodes[2][N << 1];
int curBest[2][N << 1];

int subt[N];

void dfs(int u, int p) {
	subt[u] = 1;
	for(auto id : G[u]) {
		int v = binTree[id].to(u);
		if((v != p) && (!del[id])) dfs(v, u), subt[u] += subt[v];
	}
}

int findCen(int u, int p, int sz) {
	for(auto id : G[u]) {
		int v = binTree[id].to(u);
		if((v != p) && (!del[id]) && (subt[v] * 2 > sz)) return findCen(v, u, sz);
	}
	return u;
}

int findEdge(int u, int sz) {
	int minDiff = 2e9, idx = -1;
	for(auto id : G[u]) {
		int v = binTree[id].to(u);
		if(del[id]) continue;
		if((sz - (sz - subt[v])) < minDiff)
			idx = id, minDiff = sz - (sz - subt[v]);
	}
	return idx;
}

long long h[N << 1];

void push(int u, int p, int c) {
	if(u < n) {
		rootsOf[u].emplace_back(c);
		if(h[u] + value[u] < inf) nodes[c < 0][abs(c)].emplace_back(uwu(h[u] + value[u], u));
	}
	for(auto id : G[u]) {
		int v = binTree[id].to(u);
		if(v == p || del[id]) continue;
		h[v] = h[u] + binTree[id].w;
		push(v, u, c);
	}
}

void build(int u) {
	dfs(u, u);
	if(subt[u] == 1) return;

	u = findCen(u, u, subt[u]);
	int id = findEdge(u, subt[u]);
	Edge e = binTree[id];

	del[id] = 1;
	h[e.u] = h[e.v] = 0;
	push(e.u, e.u, id), push(e.v, e.v, -id);
	build(e.u), build(e.v);
}

// this means u is the curBest in some centroid
void mergeVertice(int u) {
	partOfMst[u] = 1;
	for(int e : rootsOf[u]) {
		int c = e < 0, id = abs(e);
		for(int &i = curBest[c][id]; partOfMst[nodes[c][id][i].second] && (nodes[c][id][i].first < inf); ++ i){			
			uwu cur = nodes[c ^ 1][id][curBest[c ^ 1][id]];
			cur.first += nodes[c][id][i].first + binTree[id].w;
			if(cur.first < inf) candidates.push(cur);
		}
	}	
}

// end of centroid
int treeSize;
long long Ans = 0;

int main(){
	n = read();
	for(int i = 0; i < n; value[i ++] = read());
	for(int i = 1; i < n; ++ i) {
		int u = read() - 1, v = read() - 1, w = read();
		edge[i] = Edge(u, v, w);
		G[u].emplace_back(i);
		G[v].emplace_back(i);
	}
	pre_dfs(0, 0);

	treeSize = n;
	binTree.emplace_back(Edge(0, 0, 0));
	for(int u = 0; u < n; ++ u)
		if(G[u].size() > 2) {	
			int m = (int)G[u].size();
			// label the nodes of the current nodes from m to (m << 1) - 1
			// parent of node i should be i / 2, if i / 2 == 1 then the parent of i should be u
			for(int i = 0; i < m; ++ i) {
				int id = G[u][i], v = edge[id].to(u), x = treeSize + ((i + m) >> 1);
				if(x == treeSize + 1) binTree.emplace_back(Edge(v, u, edge[id].w));
					else binTree.emplace_back(Edge(v, x, edge[id].w));
			}
			for(int i = 2; i < m; ++ i)
				if(i / 2 > 1) binTree.emplace_back(Edge(treeSize + i, treeSize + i / 2, 0));
					else binTree.emplace_back(Edge(treeSize + i, u, 0));

			treeSize += m;
		} else for(auto id : G[u]) binTree.emplace_back(Edge(edge[id].to(u), u, edge[id].w));

	for(int i = 0; i < n; ++ i) G[i].clear();
	for(int i = 1; i < (int)binTree.size(); ++ i) {
		int u = binTree[i].u, v = binTree[i].v;
		G[u].emplace_back(i);
		G[v].emplace_back(i);
	}

	build(0);
	for(int j = 0; j < 2; ++ j)
		for(int i = 1; i < (int)binTree.size(); ++ i) {
			nodes[j][i].emplace_back(uwu(inf, 0));
			sort(nodes[j][i].begin(), nodes[j][i].end());
		}

	candidates.push(uwu(0ll, 0));
	while(!candidates.empty()) {
		int u = candidates.top().second;
		long long len = candidates.top().first;
		candidates.pop();

		if(partOfMst[u]) continue;
		mergeVertice(u);
		Ans += len;
	}
	printf("%lld\n", Ans);
	// cerr << fixed << setprecision(6) << (double)clock() / CLOCKS_PER_SEC << endl;
}