#include <bits/stdc++.h>
using namespace std;
const int MAX = int(2e5);
const long long INF = (long long) 1e18;
int dTime, n;
int L[MAX + 5], R[MAX + 5], A[MAX + 5], parent[MAX + 5];
long long W[MAX + 5], E[MAX + 5], tree[MAX * 4 + 5];
vector< pair<int, int> > X[MAX + 5];
void dfs(int u, int par)
{
L[u] = ++dTime;
A[dTime] = u;
parent[u] = par;
W[u] += W[par];
for (auto pr: X[u])
if (pr.first != par)
{
int v = pr.first;
E[v] = E[u] + pr.second * 2LL;
dfs(v, u);
}
R[u] = dTime;
}
void build(int left, int right, int root)
{
if (left == right)
{
int u = A[left];
tree[root] = W[u] - E[u];
return;
}
int mid = (left + right) / 2;
build(left, mid, root * 2);
build(mid + 1, right, root * 2 + 1);
tree[root] = max(tree[root * 2], tree[root * 2 + 1]);
}
long long query(int left, int right, int a, int b, int root)
{
if (left > b || right < a)
return -INF;
if (left >= a && right <= b)
return tree[root];
int mid = (left + right) / 2;
return max(query(left, mid, a, b, root * 2), query(mid + 1, right, a, b, root * 2 + 1));
}
long long solve(int u, int par, multiset<long long>& s)
{
long long res = -INF;
long long maxx = -INF;
if (!s.empty())
res = W[u] - E[u] - *s.begin();
if (par)
s.insert(W[ parent[par] ] - E[par]);
for (auto pr: X[u])
if (pr.first != par)
{
int v = pr.first;
long long curr = query(1, n, L[v], R[v], 1);
if (maxx == -INF)
maxx = curr;
else
{
res = max(res, maxx + curr - W[par] - W[u] + 2 * E[u]);
maxx = max(maxx, curr);
}
res = max(res, solve(v, u, s));
}
if (par)
s.erase(s.find(W[ parent[par] ] - E[par]));
return res;
}
int main() {
ios::sync_with_stdio(0);
cin.tie(NULL);
int t;
cin >> t;
while (t--)
{
cin >> n;
for (int i = 1; i <= n; i++)
{
cin >> W[i];
E[i] = 0;
X[i].clear();
}
for (int i = 1; i <= n - 1; i++)
{
int u, v, w;
cin >> u >> v >> w;
X[u].push_back({v, w});
X[v].push_back({u, w});
}
dTime = 0;
dfs(1, 0);
build(1, n, 1);
multiset<long long> s;
cout << solve(1, 0, s) << "\n";
}
return 0;
}