This documentation is automatically generated by online-judge-tools/verification-helper
重心分解
$O(N \log N)$
#pragma once
#include <bits/stdc++.h>
using namespace std;
struct CentroidDecomposition {
private:
    vector<bool> used;
    vector<int> sz;
    inline int calc_size(int u, int p) {
        sz[u] = 1;
        for(int v : tree[u])
            if(!used[v] && v != p) sz[u] += calc_size(v, u);
        return sz[u];
    }
    inline int find_centroid(int u, int p, const int mid) {
        for(int v : tree[u])
            if(!used[v] && v != p && sz[v] > mid)
                return find_centroid(v, u, mid);
        return u;
    }
    inline void belong_dfs(int u, int p, int centroid) {
        belong[u].push_back(centroid);
        for(int v : tree[u])
            if(!used[v] && v != p) belong_dfs(v, u, centroid);
    }
    inline int build(int u) {
        int centroid = find_centroid(u, -1, calc_size(u, -1) / 2);
        used[centroid] = true;
        belong_dfs(centroid, -1, centroid);
        for(int v : tree[centroid])
            if(!used[v]) cdtree[centroid].push_back(build(v));
        used[centroid] = false;
        return centroid;
    }
public:
    vector<vector<int>> tree, cdtree;
    vector<vector<int>> belong;  // belong[u]: u を含む連結成分の centroid たち
    int root = -1;               // root of cdtree
    explicit CentroidDecomposition(const vector<vector<int>> &g)
        : tree(g), root(-1) {}
    explicit CentroidDecomposition(int n) : tree(n), root(-1) {}
    inline void add_edge(int u, int v) {
        tree[u].push_back(v);
        tree[v].push_back(u);
    }
    // return root of cdtree
    inline int build() {
        cdtree.assign(tree.size(), {});
        used.assign(tree.size(), false);
        sz.resize(tree.size());
        belong.assign(tree.size(), {});
        return root = build(0);
    }
};
/*
 * @brief Centroid-Decomposition
 * @docs docs/centroid-decomposition.md
 */#line 2 "graph/centroid-decomposition.cpp"
#include <bits/stdc++.h>
using namespace std;
struct CentroidDecomposition {
private:
    vector<bool> used;
    vector<int> sz;
    inline int calc_size(int u, int p) {
        sz[u] = 1;
        for(int v : tree[u])
            if(!used[v] && v != p) sz[u] += calc_size(v, u);
        return sz[u];
    }
    inline int find_centroid(int u, int p, const int mid) {
        for(int v : tree[u])
            if(!used[v] && v != p && sz[v] > mid)
                return find_centroid(v, u, mid);
        return u;
    }
    inline void belong_dfs(int u, int p, int centroid) {
        belong[u].push_back(centroid);
        for(int v : tree[u])
            if(!used[v] && v != p) belong_dfs(v, u, centroid);
    }
    inline int build(int u) {
        int centroid = find_centroid(u, -1, calc_size(u, -1) / 2);
        used[centroid] = true;
        belong_dfs(centroid, -1, centroid);
        for(int v : tree[centroid])
            if(!used[v]) cdtree[centroid].push_back(build(v));
        used[centroid] = false;
        return centroid;
    }
public:
    vector<vector<int>> tree, cdtree;
    vector<vector<int>> belong;  // belong[u]: u を含む連結成分の centroid たち
    int root = -1;               // root of cdtree
    explicit CentroidDecomposition(const vector<vector<int>> &g)
        : tree(g), root(-1) {}
    explicit CentroidDecomposition(int n) : tree(n), root(-1) {}
    inline void add_edge(int u, int v) {
        tree[u].push_back(v);
        tree[v].push_back(u);
    }
    // return root of cdtree
    inline int build() {
        cdtree.assign(tree.size(), {});
        used.assign(tree.size(), false);
        sz.resize(tree.size());
        belong.assign(tree.size(), {});
        return root = build(0);
    }
};
/*
 * @brief Centroid-Decomposition
 * @docs docs/centroid-decomposition.md
 */