Centroid Decomposition - YessineJallouli/Competitive-Programming GitHub Wiki
Count the number of distinct paths that consist of exactly k edges.
#include<bits/stdc++.h>typedeflonglong ll;
usingnamespacestd;constint N = 2e5+7;
bool marked[N];
int subtree_size[N];
vector<int> tree[N];
int cnt[N]{1};
longlong ans = 0;
int mxDepth = 0;
int k;
intgetSubtreeSize(int node, int par = -1) {
subtree_size[node] = 1;
for (int i : tree[node]) {
if (i != par && ! marked[i]) {
subtree_size[node]+= getSubtreeSize(i, node);
}
}
return subtree_size[node];
}
intget_centroid(int node, int sz, int par = -1) {
for (int i : tree[node]) {
if (i != par && ! marked[i]) {
if (subtree_size[i]*2 > sz) {
returnget_centroid(i, sz, node);
}
}
}
return node;
}
voidget_cnt(int node, bool filling, int par, int depth = 1) {
if (depth > k)
return;
mxDepth = max(depth, mxDepth);
if (filling)
cnt[depth]++;
else
ans+= cnt[k-depth];
for (int i : tree[node]) {
if (i != par && ! marked[i]) {
get_cnt(i, filling, node, depth+1);
}
}
}
voidcentroid(int node = 1) {
int c = get_centroid(node, getSubtreeSize(node));
mxDepth = 1;
for (int i : tree[c]) {
if (! marked[i]) {
get_cnt(i, false, c);
get_cnt(i, true, c);
}
}
marked[c] = true;
fill(cnt+1, cnt+mxDepth+1, 0);
for (int i : tree[c]) {
if (! marked[i]) {
centroid(i);
}
}
}
intmain() {
int n;
cin >> n >> k;
for (int i = 0; i < n-1; i++) {
int a,b; cin >> a >> b;
tree[a].push_back(b);
tree[b].push_back(a);
}
centroid();
cout << ans;
}
Count the number of distinct paths that have at least k1 and at most k2 edges.
#include<bits/stdc++.h>typedeflonglong ll;
usingnamespacestd;constint N = 2e5+7;
bool marked[N];
int subtree_size[N];
vector<int> tree[N];
ll fenTree[N];
voidupd(int x, ll val) {
for (; x < N; x+=x&(-x)) {
fenTree[x]+= val;
}
}
ll get(int x) {
ll res = 0;
for (; x; x-=x&(-x)) {
res+= fenTree[x];
}
return res;
}
ll getRange(int a, int b) {
if (a == 0)
returnget(b);
returnget(b) - get(a-1);
}
longlong ans = 0;
int mxDepth = 0;
int l,r;
intget_subtree_sizes(int node, int parent = -1) {
subtree_size[node] = 1;
for (int i : tree[node])
if (!marked[i] && i != parent)
subtree_size[node] += get_subtree_sizes(i, node);
return subtree_size[node];
}
intget_centroid(int node, int sz, int par = -1) {
for (int i : tree[node]) {
if (i != par && ! marked[i]) {
if (subtree_size[i]*2 > sz) {
returnget_centroid(i, sz, node);
}
}
}
return node;
}
voidget_cnt(int node, bool filling, int par, int depth = 1) {
if (depth > r)
return;
mxDepth = max(depth, mxDepth);
if (filling) {
upd(depth+1, 1);
}
else {
ans+= getRange(max(1,l-depth+1), r-depth+1);
}
for (int i : tree[node]) {
if (i != par && ! marked[i]) {
get_cnt(i, filling, node, depth+1);
}
}
}
voidcentroid(int node = 1) {
int c = get_centroid(node, get_subtree_sizes(node));
mxDepth = 1;
for (int i : tree[c]) {
if (! marked[i]) {
get_cnt(i, false, c);
get_cnt(i, true, c);
}
}
marked[c] = true;
for (int i = 1; i <= mxDepth+1; i++) {
ll val = getRange(i,i);
upd(i,-val);
}
upd(1, 1);
for (int i : tree[c]) {
if (! marked[i]) {
centroid(i);
}
}
}
intmain() {
ios_base::sync_with_stdio(false), cin.tie(nullptr);
int n;
cin >> n >> l >> r;
upd(1,1);
for (int i = 0; i < n-1; i++) {
int a,b; cin >> a >> b;
tree[a].push_back(b);
tree[b].push_back(a);
}
centroid();
cout << ans;
}