給定 N (≤200,000) 節點樹,邊有長度,求長度恰好等於 K (≤1,000,000) 的路徑中邊數最小值。樹分治核心:選重心分解,統計過重心路徑,遞歸處理子樹。
統計所有距離和為 K 的路徑對,記錄各深度出現次數。最後掃描深度數組找最小有效深度。避免了難以處理的"最小值減法"問題。
void Find_Centre_Of_Gravity(int x, int size, int &cg) {
// 計算子樹大小,判斷是否為重心
}
void DFS1(int x, int d, int deep, int from) {
// 記錄距離 dis[x] 和深度 dpt[x]
}
void Calculate(int x, int flag) {
// 收集當前子樹所有節點 (距離, 深度)
// 排序後雙指針查找距離和為 K 的配對
// ans[深度和] += flag (1: 加入, -1: 排除當前子樹內部配對)
}
void Tree_Divide_And_Conquer(int root, int size) {
int cg; Find_Centre_Of_Gravity(root, size, cg);
DFS1(cg, 0, 0, 0);
Calculate(cg, 1);
for (子樹) {
標記邊禁用;
Calculate(子樹根, -1); // 排除子樹內部配對
Tree_Divide_And_Conquer(子樹根, 子樹大小);
}
}