質問の意味:
ツリーが与えられると、各側は、特定の辺の重みを有しています。
そして、ポイント間のパスを求める(3 \)\ポイントの数の倍数です。
アイデア:
点線のルールテンプレートのタイトル。
問題は、ポイントを介して変換することができる\(T \)経路点を通過しない\(T \)直接再帰的に処理することができ、両方の場合においてパス、。
サブ問題に\(DFS \)再びサブツリーのルートノードまでの残りの距離の全ての点に対処し、次いで3で割った距離の残りの部分を取得する、選挙に係る残りがあってもよいです。
エッジを繰り返し選択することができる2つの点があり、それのでも包含排除に留意されたいです。
とにかく、それは〜テンプレートです
#include <bits/stdc++.h>
#define MP make_pair
#define fi first
#define se second
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int N = 20005;
int n;
vector <pii> g[N];
int sz[N], mx[N], tsz;
int d[N];
int rt, ans, cnt;
bool vis[N];
void getrt(int u, int fa) {
sz[u] = 1; mx[u] = 0;
for(auto it : g[u]) {
int v = it.fi;
if(v == fa || vis[v]) continue;
getrt(v, u);
sz[u] += sz[v];
if(sz[v] > mx[u]) mx[u] = sz[v];
}
mx[u] = max(mx[u], tsz - sz[u]);
if(mx[u] < mx[rt]) rt = u;
}
void dfs2(int u, int D, int fa) {
d[++cnt] = D;
for(auto it : g[u]) {
int v = it.fi, w = it.se;
if(vis[v] || v == fa) continue;
dfs2(v, D + w, u);
}
}
int calc() {
for(int i = 1; i <= cnt; i++) d[i] %= 3;
int tmp[3] = {0, 0, 0};
for(int i = 1; i <= cnt; i++) ++tmp[d[i]];
int ans = tmp[0] * (tmp[0] - 1) + 2 * (tmp[1] * tmp[2]);
return ans;
}
void dfs(int u) {
vis[u] = 1;
cnt = 0; dfs2(u, 0, 0);
int tmp = calc();
ans += tmp;
for(auto it : g[u]) {
int v = it.fi, w = it.se;
if(vis[v]) continue;
cnt = 0, dfs2(v, w, 0);
ans -= calc();
tsz = sz[v], rt = 0, getrt(v, u);
dfs(rt);
}
}
int gcd(int a, int b) {
return b == 0 ? a : gcd(b, a % b);
}
int main() {
ios::sync_with_stdio(false); cin.tie(0);
cin >> n;
for(int i = 1; i < n; i++) {
int u, v, w; cin >> u >> v >> w;
g[u].push_back(MP(v, w)); g[v].push_back(MP(u, w));
}
tsz = n, mx[0] = INF, getrt(1, 0);
dfs(rt);
ans += n;
int tot = n * n;
int g = gcd(tot, ans);
ans /= g, tot /= g;
cout << ans << '/' << tot;
return 0;
}