點分治主要用來處理樹上路徑問題,可以統計樹上點到點的所有路徑,複雜度o(nlogn)基於樹上的結點進行分治,不斷將一棵樹拆成多顆子樹處理
選擇點時為了防止退化成鏈的情況,如果選點後左右子樹越大,遞迴層數越多,時間越慢,反之則越快,我們每次選擇子樹內的重心
void getroot(int u, int fa)
f[u] = max(f[u], sum - sz[u]);
if (f[u] < f[root]) root = u;
}
分治時每次選擇當前重心計算結果,遞迴處理子樹,容斥一下結果
void solve(int u)
}
每次選擇乙個重心之後我們需要統計它到其他的點的路徑,之後兩兩合併,計算對結果的貢獻
void getdis(int u, int dis, int fa)
}void cal(int u, int dis, int add)
}for (int i = 0; i < 3; ++i) o[i] = num[i] = 0;
}
記錄的例題poj1741
#include #include #include #include #include using namespace std;
typedef long long ll;
const int maxn = 1e4 + 5;
vector< pair>e[maxn];
int n, k;
int root, sum, vis[maxn], sz[maxn], f[maxn];
int dis[maxn], tot;
ll ans;
void getroot(int u, int fa)
f[u] = max(f[u], sum - sz[u]);
if (f[u] < f[root]) root = u;
}void getdis(int u, int dist, int fa)
}void calc(int u, int dist, int add)
else r--;
}}void solve(int u)
}int main()
ans = 0; sum = n; root = 0; f[0] = 0x3f3f3f;
getroot(1, 0); solve(root);
printf("%lld\n", ans);
}}
點分治學習筆記
關於點分治,其實思想是非常好理解的,模擬在數列上或是在平面上的分治演算法 如歸併排序,平面最近點對等 我們可以從字面上理解該演算法 以乙個點為界限,將一棵樹分成若干個子樹,當劃分到一定規模,就對每個子樹分別進行求解 感性理解就好了 感受乙個演算法最直觀的辦法,就是來看一道模板題。給定一棵有 n 個點...
點分治學習筆記
point divide and rule 澱粉質就是在樹上,依靠不停的遞迴和分治,解決相同的子問題 先來看看模板題 tree 就是找樹上 k 的路徑有多少 我們可以分兩種情況討論 1.經過根節點 p 的路徑 2.不經過根節點 p 的路徑 第二種情況可以通過遞迴來處理,我們直接來討論第一種情況 設當...
點分治學習筆記
銀月城傳送門 集訓day9上午各種神仙分治真心聽不懂,自己頹著把點分治學了,簡單 並不 寫一下再加深一下理解吧。一 點分治是個啥 點分治是通常用來處理樹上路徑統計問題的一種分治方法。尤其適用於大規模的資料處理。時間複雜度最高為o nlogn 例如求樹上兩點間距離,點分治就遠優於dfs求兩點距離 o ...