#50351: 乘起來,不用換根


s10900156@nhsh.tp.edu.tw (ShanC)

學校 : 臺北市立內湖高級中學
編號 : 138785
來源 : [118.167.202.23]
最後登入時間 :
2024-11-29 20:43:48

對於每個節點,要算他們的答案,最快就是把每個子樹的大小算好。
根據路徑在樹上的唯一性,設 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);
    }
}