#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;
}