//gpt
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int MAXN = 200000 + 5;
const int H = 18; // log2(MAXN) ≲ 18
int N;
vector<pair<int,int>> g[MAXN];
ll W[MAXN];
// — your centroid template arrays —
int sub[MAXN], cth[MAXN], ctp[MAXN];
int dist_arr[MAXN][H+1];
/// 1) compute subtree sizes on active nodes (cth[v]==0)
void dfs_siz(int u, int f){
sub[u] = 1;
for (auto &e : g[u]) {
int v = e.first;
if (v==f || cth[v]!=0) continue;
dfs_siz(v, u);
sub[u] += sub[v];
}
}
/// 2) find the centroid of a component
int fc(int u, int f, int lim){
for (auto &e : g[u]) {
int v = e.first;
if (v==f || cth[v]!=0) continue;
if (sub[v] > lim)
return fc(v, u, lim);
}
return u;
}
/// 3) (unused) fill dist_arr[u][h]
void dfs_dist(int u, int f, int d, int h){
dist_arr[u][h] = d;
for (auto &e : g[u]) {
int v = e.first;
if (v==f || cth[v]!=0) continue;
dfs_dist(v, u, d+1, h);
}
}
/// We'll collect (value, depth) pairs from each subtree:
/// value = sum W[...] - 2*sum C[...] along path from centroid's child
/// depth = the number of edges from centroid
void dfs_collect(int u, int f, ll curr, int depth,
vector<pair<ll,int>>& vals)
{
vals.emplace_back(curr, depth);
for (auto &e : g[u]) {
int v = e.first, c = e.second;
if (v==f || cth[v]!=0) continue;
dfs_collect(v, u,
curr + W[v] - 2LL*c,
depth+1,
vals);
}
}
ll answer;
/// 4) the modified decompose() that updates `answer`
void decompose(int entry, int parent=0, int height=1){
// a) find centroid
dfs_siz(entry, 0);
int cent = fc(entry, 0, sub[entry]>>1);
// b) (opt) compute dist_arr for this level
dfs_dist(cent, 0, 0, height);
// c) for all paths that pass through `cent`:
// we need two kinds:
// 1) centroid-to-node at distance>=2
// 2) node-in-subtree1 -> centroid -> node-in-subtree2
ll bestVal = LLONG_MIN;
for (auto &e : g[cent]) {
int v = e.first, c = e.second;
if (cth[v]!=0) continue;
vector<pair<ll,int>> vals;
// start from the child edge (cent->v):
dfs_collect(v, cent,
W[v] - 2LL*c,
1, // depth=1 for v
vals);
// 1) centroid-to-node: only valid if depth>=2 (so cent and node not adjacent)
for (auto &pr : vals) {
ll d = pr.first;
int depth = pr.second;
if (depth >= 2) {
answer = max(answer, d + W[cent]);
}
}
// 2) cross-subtree pairing
for (auto &pr : vals) {
ll d = pr.first;
if (bestVal != LLONG_MIN) {
answer = max(answer, bestVal + d + W[cent]);
}
}
// absorb this subtree's endpoint‐values
for (auto &pr : vals) {
bestVal = max(bestVal, pr.first);
}
}
// d) finalize centroid
cth[cent] = height;
ctp[cent] = parent;
// e) recurse on each remaining component
for (auto &e : g[cent]) {
int v = e.first;
if (cth[v]==0)
decompose(v, cent, height+1);
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
while (T--) {
cin >> N;
for (int i = 1; i <= N; i++) {
cin >> W[i];
g[i].clear();
cth[i] = 0;
}
for (int i = 0; i < N-1; i++){
int u,v,c;
cin >> u >> v >> c;
g[u].emplace_back(v,c);
g[v].emplace_back(u,c);
}
answer = LLONG_MIN;
decompose(1, 0, 1);
cout << answer << "\n";
}
return 0;
}