#include int ri() { int n; scanf("%d", &n); return n; } std::vector > > hen; std::vector alive; std::vector size; void dfs(int i, int prev) { size[i] = 1; for (auto j : hen[i]) if (j.first != prev && alive[j.first]) { dfs(j.first, i); size[i] += size[j.first]; } } int get_centroid(int i) { dfs(i, -1); while (1) { int max = 0; int maxindex = -1; for (auto j : hen[i]) if (alive[j.first] && size[j.first] < size[i] && max < size[j.first]) max = size[j.first], maxindex = j.first; if (max > size[i] / 2) i = maxindex; else break; } return i; } int64_t res = 0; std::vector > path_color; void centroid_rec(int i) { i = get_centroid(i); struct Info { std::map, int> two_match; std::map two_side; std::map one; int one_num = 0; }; std::vector infos; for (auto j : hen[i]) { if (!alive[j.first]) continue; infos.push_back({}); Info &info = infos.back(); std::queue > que; path_color[j.first] = {j.second, -1}; que.push({j.first, i}); while (que.size()) { auto k = que.front(); auto &cur_color = path_color[k.first]; que.pop(); if (cur_color.second != -1) { if (cur_color.second < cur_color.first) std::swap(cur_color.first, cur_color.second); info.two_match[cur_color]++; info.two_side[cur_color.first]++; info.two_side[cur_color.second]++; } else { info.one_num++; info.one[cur_color.first]++; } for (auto l : hen[k.first]) if (l.first != k.second && alive[l.first]) { path_color[l.first] = cur_color; if (path_color[l.first].first != l.second) { if (path_color[l.first].second == -1) path_color[l.first].second = l.second; else if (path_color[l.first].second != l.second) continue; } que.push({l.first, k.first}); } } } Info all; for (auto &j : infos) { for (auto &k : j.two_match) all.two_match[k.first] += k.second; for (auto &k : j.two_side) all.two_side[k.first] += k.second; for (auto &k : j.one) all.one[k.first] += k.second; all.one_num += j.one_num; } auto calc = [&] (Info &target, Info &main) { int64_t res = 0; for (auto &j : main.two_match) { res += (int64_t) j.second * target.two_match[j.first]; res += (int64_t) j.second * (target.one[j.first.first] + target.one[j.first.second]); } for (auto &j : main.one) { res += (int64_t) j.second * target.two_side[j.first]; res += (int64_t) j.second * (target.one_num - target.one[j.first]); } return res; }; for (auto &j : infos) res += calc(all, j) - calc(j, j); for (auto &j : all.two_match) res += j.second * 2; alive[i] = false; for (auto &j : hen[i]) if (alive[j.first]) centroid_rec(j.first); } void run() { int n = hen.size(); alive.resize(n, true); size.resize(n); path_color.resize(n); centroid_rec(0); res /= 2; } int main() { int n = ri(); int k = ri(); hen.resize(n); for (int i = 1; i < n; i++) { int x = ri() - 1; int y = ri() - 1; int c = ri() - 1; hen[x].push_back({y, c}); hen[y].push_back({x, c}); } run(); printf("%" PRId64 "\n", res); return 0; }