diff --git a/algorithms/graph/centroid_decomposition.cpp b/algorithms/graph/centroid_decomposition.cpp new file mode 100644 index 0000000000000000000000000000000000000000..80a783d622e848d118b84447f81ada4f9c92310f --- /dev/null +++ b/algorithms/graph/centroid_decomposition.cpp @@ -0,0 +1,65 @@ +/// Centroid Decomposition +/// +/// Complexity (Time): O(V log V) +/// Complexity (Space): O(V + E) + +// Must be a tree +vector<int> graph[MAX]; + +struct CentroidDecomposition { + vector<int> par, size, marked; + + CentroidDecomposition(int N) : + par(N), size(N), marked(N) + { + init(); + } + + void init() { + fill(all(marked), 0); + build(0, -1); + } + + /// Builds the centroid decomposition of the tree recursively. + /// @param x initial node + /// @param p parent node + void build(int x, int p) { + int n = dfs(x, -1); + int centroid = get_centroid(x, -1, n); + + marked[centroid] = 1; + par[centroid] = p; + + for (auto i : graph[centroid]) + if (!marked[i]) + build(i, centroid); + } + + /// Calculates size of every subtree (in the original tree). + /// @param x initial node + /// @param p parent node + int dfs(int x, int p) { + size[x] = 1; + for (auto i : graph[x]) + if (i != p && !marked[i]) + size[x] += dfs(i, x); + + return size[x]; + } + + /// Finds centroid by recursively searching for it in the subtree + /// with more than n / 2 nodes in it. + /// @param x initial node + /// @param p parent node + /// @param n size of initial subtree + int get_centroid(int x, int p, int n) { + for (auto i : graph[x]) + if (i != p && size[i] > n / 2 && !marked[i]) + return get_centroid(i, x, n); + return x; + } + + int operator[](int i) { + return par[i]; + } +};