#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int theta;
if (!(cin >> theta)) return 0;
int n,m;
cin >> n >> m;
vector<int> color(n+1);
for (int i = 1; i <= n; ++i) cin >> color[i];
vector<vector<int>> g(n+1);
for (int i = 0; i < m; ++i){
int u,v,w; cin >> u >> v >> w;
g[u].push_back(v);
g[v].push_back(u);
}
// Preprocess: root at 1, compute tin/tout, up table, subtree sizes
int LOG = 1;
while ((1<<LOG) <= n) ++LOG;
vector<vector<int>> up(LOG, vector<int>(n+1));
vector<int> tin(n+1), tout(n+1), depth(n+1), sub(n+1);
int timer = 0;
// iterative DFS to compute tin/tout, parent, depth, subtree
vector<tuple<int,int,int>> st;
st.reserve(2*n);
st.emplace_back(1, 0, 0);
while (!st.empty()){
auto [v,p,vis] = st.back(); st.pop_back();
if (!vis){
tin[v] = ++timer;
up[0][v] = (p==0? v : p);
depth[v] = (p==0? 0 : depth[p]+1);
st.emplace_back(v,p,1);
for (int to : g[v]) if (to != p) st.emplace_back(to, v, 0);
} else {
int s = 1;
for (int to : g[v]) if (to != up[0][v]) s += sub[to];
sub[v] = s;
tout[v] = timer;
}
}
for (int k = 1; k < LOG; ++k){
for (int v = 1; v <= n; ++v) up[k][v] = up[k-1][ up[k-1][v] ];
}
auto is_anc = [&](int a,int b)->bool{ return tin[a] <= tin[b] && tout[b] <= tout[a]; };
auto lca = [&](int a,int b){
if (is_anc(a,b)) return a;
if (is_anc(b,a)) return b;
for (int k = LOG-1; k >= 0; --k) if (!is_anc(up[k][a], b)) a = up[k][a];
return up[0][a];
};
// group nodes by color
vector<vector<int>> by_color(n+1);
for (int v = 1; v <= n; ++v) by_color[color[v]].push_back(v);
// difference array on Euler to add to subtree intervals
vector<ll> diff(n+3, 0);
auto add_range = [&](int L,int R,ll val){
if (L > R) return;
diff[L] += val;
diff[R+1] -= val;
};
vector<int> node_at_tin(n+1);
for (int v = 1; v <= n; ++v) node_at_tin[tin[v]] = v;
// temporary containers
vector<int> nodes; nodes.reserve(1024);
vector<int> stk2; stk2.reserve(1024);
vector<vector<int>> vt(n+1);
for (int col = 1; col <= n; ++col){
auto &vec = by_color[col];
if (vec.empty()) continue;
// sort colored nodes by tin (for binary searching counts)
sort(vec.begin(), vec.end(), [&](int a,int b){ return tin[a] < tin[b]; });
// build virtual tree node set: colored nodes + LCAs
nodes.clear();
for (int x : vec) nodes.push_back(x);
int origin_sz = nodes.size();
for (int i = 0; i + 1 < origin_sz; ++i){
nodes.push_back(lca(nodes[i], nodes[i+1]));
}
sort(nodes.begin(), nodes.end(), [&](int a,int b){ if (tin[a]==tin[b]) return a<b; return tin[a] < tin[b]; });
nodes.erase(unique(nodes.begin(), nodes.end()), nodes.end());
// build virtual tree adjacency
for (int x : nodes) vt[x].clear();
stk2.clear();
for (int x : nodes){
while (!stk2.empty() && !is_anc(stk2.back(), x)) stk2.pop_back();
if (!stk2.empty()) vt[stk2.back()].push_back(x);
stk2.push_back(x);
}
// helper: count how many colored nodes lie inside subtree v
auto cnt_in_subtree = [&](int v)->int{
auto lo = lower_bound(vec.begin(), vec.end(), tin[v], [&](int node,int value){ return tin[node] < value; });
auto hi = upper_bound(vec.begin(), vec.end(), tout[v], [&](int value,int node){ return value < tin[node]; });
return int(hi - lo);
};
// process virtual nodes
for (int v : nodes){
int is_colored = (binary_search(vec.begin(), vec.end(), v, [&](int a,int b){ return tin[a] < tin[b]; })
|| (tin[vec[ lower_bound(vec.begin(), vec.end(), tin[v], [&](int node,int value){ return tin[node] < value; }) - vec.begin() ]] == tin[v] )
) ? 0 : 0;
// simpler check:
bool v_is_col = false;
auto itv = lower_bound(vec.begin(), vec.end(), tin[v], [&](int node,int value){ return tin[node] < value; });
if (itv != vec.end() && tin[*itv] == tin[v]) v_is_col = true;
// sum subtree sizes of virtual children
ll sum_ch_sub = 0;
for (int c : vt[v]) sum_ch_sub += sub[c];
if (!v_is_col){
// remainder in subtree[v] not covered by children in VT -> a single connected block
ll block_sz = (ll)sub[v] - sum_ch_sub;
if (block_sz > 0){
ll val = (ll)n - block_sz;
// add val to subtree[v]
add_range(tin[v], tout[v], val);
// subtract from each vt-child subtree
for (int c : vt[v]) add_range(tin[c], tout[c], -val);
}
} else {
// v is a colored node: each original neighbor side that contains 0 colored nodes becomes a component
// we iterate all neighbors in original tree (g[v])
for (int to : g[v]){
int side_sz;
int cnt_col_side;
if (up[0][to] == v){ // to is child of v
side_sz = sub[to];
cnt_col_side = cnt_in_subtree(to);
if (cnt_col_side == 0){
ll val = (ll)n - side_sz;
add_range(tin[to], tout[to], val);
}
} else if (up[0][v] == to){ // to is parent of v
side_sz = n - sub[v];
// number of colored nodes outside subtree[v] = total colored - cnt_in_subtree(v)
int total_col = (int)vec.size();
int inside = cnt_in_subtree(v);
cnt_col_side = total_col - inside;
if (cnt_col_side == 0){
ll val = (ll)n - side_sz;
// nodes outside subtree[v] are two intervals: [1, tin[v]-1] and [tout[v]+1, n]
if (tin[v] > 1) add_range(1, tin[v]-1, val);
if (tout[v] < n) add_range(tout[v]+1, n, val);
}
} else {
// should not happen in tree adjacency
}
}
// colored node itself contributes n (path from v to any vertex contains its color)
add_range(tin[v], tin[v], n);
}
}
}
// accumulate diff to answer
vector<ll> ans(n+1, 0);
ll cur = 0;
for (int t = 1; t <= n; ++t){
cur += diff[t];
ans[node_at_tin[t]] = cur;
}
for (int i = 1; i <= n; ++i){
if (i>1) cout << ' ';
cout << ans[i];
}
cout << '\n';
return 0;
}