樹上求無序三元組 (x,y,z) 互不相同且 dis(x,y)=dis(y,z)=dis(x,z)。N ≤ 5000。
故只需枚舉中心點,統計各分支各深度節點數,組合計算。
對每個節點 u 作中心:
v,DFS 統計 cnt[d] = 深度 d 的節點數d,三元組數 += 選三條不同分支各取一個深度 d 節點用前綴和優化合併:f[d] = 已處理分支深度 d 總數,g[d] = 兩分支組合數。新分支 cnt[d] 貢獻 g[d] * cnt[d],更新 g[d] += f[d] * cnt[d],f[d] += cnt[d]。
#include <bits/stdc++.h> using namespace std; const int MAXN = 5050; vectorG[MAXN]; int n; long long ans = 0; int temp[MAXN], f[MAXN], g[MAXN]; void dfs(int u, int p, int dpt) { temp[dpt]++; for (int v : G[u]) if (v != p) dfs(v, u, dpt + 1); } int main() { ios::sync_with_stdio(false); cin.tie(nullptr); cin >> n; for (int i = 1; i < n; i++) { int u, v; cin >> u >> v; G[u].push_back(v); G[v].push_back(u); } for (int u = 1; u <= n; u++) { fill(f, f + n + 1, 0); fill(g, g + n + 1, 0); for (int v : G[u]) { fill(temp, temp + n + 1, 0); dfs(v, u, 1); for (int d = 1; d <= n; d++) { ans += 1LL * g[d] * temp[d]; g[d] += f[d] * temp[d]; f[d] += temp[d]; } } } cout << ans << '\n'; return 0; }
f,g 陣列將 O(度²) 降為 O(度)long long