#pragma GCC optimize("O3,unroll-loops")
#include <bits/stdc++.h>
#define ll long long
#define itachi ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define fi first
#define se second
#define maxn 500005

using namespace std;

int32_t n;
int32_t sz[maxn];
bool banned[maxn];
int32_t cnt[maxn];
int32_t delta_only[maxn], delta_all[maxn];
int32_t delta_only_inside[maxn], delta_all_inside[maxn];
vector<pair<int32_t, int32_t>> adj[maxn];

long long ans = 0;
int32_t sum_only = 0;
int32_t sum_only_inside = 0;
vector<int32_t> usedDelta, usedInside;
int32_t current_root = 0;

void get_sz(int32_t u, int32_t p) {
    sz[u] = 1;
    for (const auto& [v, w] : adj[u]) {
        if (v != p && !banned[v]) {
            get_sz(v, u);
            sz[u] += sz[v];
        }
    }
}

void countChild(int32_t u, int32_t p, int32_t c) {
    sz[u] = 1;
    bool first = false;

    if (u != current_root) first = (++cnt[c] == 1);

    for (const auto& [v, w] : adj[u]) {
        if (v == p || banned[v]) continue;
        countChild(v, u, w);
        sz[u] += sz[v];
    }

    if (u != current_root) {
        if (first) {
            sum_only += sz[u];
            if (delta_all[c] == 0) usedDelta.push_back(c);
            delta_all[c] += sz[u];
            delta_only[c] += sz[u];
        }
        else if (cnt[c] == 2) {
            sum_only -= sz[u];
            delta_only[c] -= sz[u];
        }
        --cnt[c];
    }
}

int32_t find_cen(int32_t u, int32_t p, int32_t S) {
    for (const auto& [v, w] : adj[u]) {
        if (v != p && !banned[v] && sz[v] > S / 2) {
            return find_cen(v, u, S);
        }
    }
    return u;
}

void cntInside(int32_t u, int32_t p, int32_t c) {
    bool first = (++cnt[c] == 1);

    if (first) {
        sum_only_inside += sz[u];
        if (delta_all_inside[c] == 0) usedInside.push_back(c);
        delta_only_inside[c] += sz[u];
        delta_all_inside[c] += sz[u];
    }
    else if (cnt[c] == 2) {
        sum_only_inside -= sz[u];
        delta_only_inside[c] -= sz[u];
    }

    for (const auto& [v, w] : adj[u]) {
        if (v == p || banned[v]) continue;
        cntInside(v, u, w);
    }

    --cnt[c];
}

void addRootPaths(int32_t u, int32_t p, int32_t distinct, int32_t c) {
    bool first = (++cnt[c] == 1);
    if (first) distinct++;
    else if (cnt[c] == 2) distinct--;

    ans += 2LL * distinct;

    for (const auto& [v, w] : adj[u]) {
        if (v == p || banned[v]) continue;
        addRootPaths(v, u, distinct, w);
    }
    --cnt[c];
}

void dfs(int32_t u, int32_t p, int32_t C, int32_t only_cur, int32_t all_cur, int32_t only_out, int32_t distinctlen, int32_t ver_out) {
    bool first = (++cnt[C] == 1);

    if (first) {
        distinctlen++;
        all_cur += delta_all[C] - delta_all_inside[C];
        only_cur += delta_only[C] - delta_only_inside[C];
    }
    else if (cnt[C] == 2) {
        distinctlen--;
        all_cur -= delta_all[C] - delta_all_inside[C];
    }
    ans += 1LL * distinctlen * ver_out - all_cur - only_cur + only_out;

    for (const auto& [v, w] : adj[u]) {
        if (v == p || banned[v]) continue;
        dfs(v, u, w, only_cur, all_cur, only_out, distinctlen, ver_out);
    }

    --cnt[C];
}

void solve(int32_t u) {
    get_sz(u, 0);
    int32_t root = find_cen(u, 0, sz[u]);

    current_root = root;
    sum_only = 0;
    countChild(root, 0, 0);
    int32_t all_node = sz[root];

    for (const auto& [v, w] : adj[root]) {
        if (banned[v]) continue;
        addRootPaths(v, root, 0, w);
    }

    for (const auto& [v, w] : adj[root]) {
        if (banned[v]) continue;

        sum_only_inside = 0;
        cntInside(v, root, w);
        int32_t ver_out = all_node - sz[v] - 1;
        int32_t only_out = sum_only - sum_only_inside;

        dfs(v, root, w, 0, 0, only_out, 0, ver_out);

        for (int32_t c : usedInside) {
            delta_all_inside[c] = 0;
            delta_only_inside[c] = 0;
        }
        usedInside.clear();
    }

    banned[root] = 1;
    for (int32_t c : usedDelta) {
        delta_all[c] = 0;
        delta_only[c] = 0;
    }
    usedDelta.clear();
    for (const auto& [v, w] : adj[root]) {
        if (!banned[v]) solve(v);
    }
}

int main() {
    itachi
    cin>>n;
    for (int32_t i = 1; i < n; i++) {
        int32_t u, v, w;
        cin >> u >> v >> w;
        adj[u].push_back({v, w});
        adj[v].push_back({u, w});
    }

    solve(1);
    cout << ans / 2;
    return 0;
}
