對於每個節點,要算他們的答案,最快就是把每個子樹的大小算好。
根據路徑在樹上的唯一性,設 r 為根時,「每兩棵 r 的子樹上各挑一點所形成的點對」數量即為「通過 r 的路徑」數。
而點對數量可以直接將子樹的數量相乘,兩兩乘一遍加進答案。
以下 code 示範我的想法如何實作,把輸入輸出補完、預處理子樹大小之後,就會是答案 :
void dfs(int u, int pre){
ll res = 0;
vector<int> neighbor_sz;
for(int &v : g[u]){
if(v != pre)
neighbor_sz.push_back(sz[v]);
}
neighbor_sz.push_back(n - sz[u]);
for(int i = 0; i < neighbor_sz.size(); i++){
for(int j = i + 1; j < neighbor_sz.size(); j++){
res += neighbor_sz[i] * neighbor_sz[j];
}
}
ans[u] = res;
for(int &v : g[u]){
if(pre == v) continue;
dfs(v, u);
}
}