Skip to content

centroid_decomposition.hpp

SECTIONGraph INCLUDEnoya/centroid_decomposition.hpp

构造树的点分治层次;适合按距离维护全局动态点集、统计经过重心的路径。

Complexity: Time: O(n log n). Space: O(n).

跳到代码 · GitHub ↗

Implementation

当前头文件,省略 include guard;依赖见 #include

/// @complexity Time: O(n log n).
/// Space: O(n).

#include <cassert>
#include <vector>

namespace noya {

/// @brief Centroid-decomposition tree of an undirected tree.
struct centroid_decomposition {
  int n = 0;
  int rt = -1;
  std::vector<int> fa;
  std::vector<int> dep;
  std::vector<int> ord;

  centroid_decomposition() = default;
  explicit centroid_decomposition(const std::vector<std::vector<int>> &g) {
    build(g);
  }

  /// @brief Rebuild the centroid tree; fa[rt] is -1 and ord is the
  /// decomposition order.
  void build(const std::vector<std::vector<int>> &g) {
    n = int(g.size());
    fa.assign(n, -1);
    dep.assign(n, -1);
    ord.clear();
    if (n == 0) {
      rt = -1;
      return;
    }
    std::vector<int> siz(n);
    std::vector<bool> del(n);

    auto gsz = [&](auto &self, int u, int pre) -> int {
      siz[u] = 1;
      for (int nxt : g[u]) {
        if (nxt != pre && !del[nxt]) {
          siz[u] += self(self, nxt, u);
        }
      }
      return siz[u];
    };
    auto fc = [&](auto &self, int u, int pre, int tot) -> int {
      for (int nxt : g[u]) {
        if (nxt != pre && !del[nxt] && siz[nxt] > tot / 2) {
          return self(self, nxt, u, tot);
        }
      }
      return u;
    };
    auto dfs = [&](auto &self, int ent, int cf, int cd) -> int {
      int tot = gsz(gsz, ent, -1);
      int cen = fc(fc, ent, -1, tot);
      fa[cen] = cf;
      dep[cen] = cd;
      ord.push_back(cen);
      del[cen] = true;
      for (int nxt : g[cen]) {
        if (!del[nxt]) {
          self(self, nxt, cen, cd + 1);
        }
      }
      return cen;
    };
    rt = dfs(dfs, 0, -1, 0);
  }
};

} // namespace noya
#ifndef NOYA_CENTROID_DECOMPOSITION_HPP
#define NOYA_CENTROID_DECOMPOSITION_HPP 1

/// @complexity Time: O(n log n).
/// Space: O(n).

#include <cassert>
#include <vector>

namespace noya {

/// @brief Centroid-decomposition tree of an undirected tree.
struct centroid_decomposition {
  int n = 0;
  int rt = -1;
  std::vector<int> fa;
  std::vector<int> dep;
  std::vector<int> ord;

  centroid_decomposition() = default;
  explicit centroid_decomposition(const std::vector<std::vector<int>> &g) {
    build(g);
  }

  /// @brief Rebuild the centroid tree; fa[rt] is -1 and ord is the
  /// decomposition order.
  void build(const std::vector<std::vector<int>> &g) {
    n = int(g.size());
    fa.assign(n, -1);
    dep.assign(n, -1);
    ord.clear();
    if (n == 0) {
      rt = -1;
      return;
    }
    std::vector<int> siz(n);
    std::vector<bool> del(n);

    auto gsz = [&](auto &self, int u, int pre) -> int {
      siz[u] = 1;
      for (int nxt : g[u]) {
        if (nxt != pre && !del[nxt]) {
          siz[u] += self(self, nxt, u);
        }
      }
      return siz[u];
    };
    auto fc = [&](auto &self, int u, int pre, int tot) -> int {
      for (int nxt : g[u]) {
        if (nxt != pre && !del[nxt] && siz[nxt] > tot / 2) {
          return self(self, nxt, u, tot);
        }
      }
      return u;
    };
    auto dfs = [&](auto &self, int ent, int cf, int cd) -> int {
      int tot = gsz(gsz, ent, -1);
      int cen = fc(fc, ent, -1, tot);
      fa[cen] = cf;
      dep[cen] = cd;
      ord.push_back(cen);
      del[cen] = true;
      for (int nxt : g[cen]) {
        if (!del[nxt]) {
          self(self, nxt, cen, cd + 1);
        }
      }
      return cen;
    };
    rt = dfs(dfs, 0, -1, 0);
  }
};

} // namespace noya

#endif // NOYA_CENTROID_DECOMPOSITION_HPP
#include <cassert>
#include <vector>

/// @complexity Time: O(n log n).
/// Space: O(n).

namespace noya {

/// @brief Centroid-decomposition tree of an undirected tree.
struct centroid_decomposition {
  int n = 0;
  int rt = -1;
  std::vector<int> fa;
  std::vector<int> dep;
  std::vector<int> ord;

  centroid_decomposition() = default;
  explicit centroid_decomposition(const std::vector<std::vector<int>> &g) {
    build(g);
  }

  /// @brief Rebuild the centroid tree; fa[rt] is -1 and ord is the
  /// decomposition order.
  void build(const std::vector<std::vector<int>> &g) {
    n = int(g.size());
    fa.assign(n, -1);
    dep.assign(n, -1);
    ord.clear();
    if (n == 0) {
      rt = -1;
      return;
    }
    std::vector<int> siz(n);
    std::vector<bool> del(n);

    auto gsz = [&](auto &self, int u, int pre) -> int {
      siz[u] = 1;
      for (int nxt : g[u]) {
        if (nxt != pre && !del[nxt]) {
          siz[u] += self(self, nxt, u);
        }
      }
      return siz[u];
    };
    auto fc = [&](auto &self, int u, int pre, int tot) -> int {
      for (int nxt : g[u]) {
        if (nxt != pre && !del[nxt] && siz[nxt] > tot / 2) {
          return self(self, nxt, u, tot);
        }
      }
      return u;
    };
    auto dfs = [&](auto &self, int ent, int cf, int cd) -> int {
      int tot = gsz(gsz, ent, -1);
      int cen = fc(fc, ent, -1, tot);
      fa[cen] = cf;
      dep[cen] = cd;
      ord.push_back(cen);
      del[cen] = true;
      for (int nxt : g[cen]) {
        if (!del[nxt]) {
          self(self, nxt, cen, cd + 1);
        }
      }
      return cen;
    };
    rt = dfs(dfs, 0, -1, 0);
  }
};

} // namespace noya