The rerooting technique

rerooting 是求解一类与树相关的问题的技巧。这类问题的特征:

  1. 定义了一个以有根树为自变量的函数 \(f\)
  2. 给你一个树 \(T\)
  3. 需要求出函数 \(f\) 在以 \(T\) 的每个点为根所得到的有根树上的值。

rerooting 在李煜东的《算法竞赛进阶指南》上名为“二次扫描与换根法”。

记号

\(T_{r,u}\):树 \(T\) 以点 \(r\) 为根的有根树里以点 \(u\) 为根的子树。

\(T_u := T_{u,u}\)

\(g\) 是一个关于有根树的函数。

\(g(r, u):= g(T_{r,u})\)

\(g(r) := g(r, r)\)

Rerooting 的代码实现

过程

第一次扫描:通过典型的树上DP算出 \(f(1)\)

第二次扫描:深度优先遍历 \(T_1\),算出余下 \(n - 1\) 个点的 \(f\) 值。

代码框架

#include <vector>
const int max_n = 100000;              // number of vertices of the tree
std::vector<std::vector<int>> g(max_n);// store the tree, vertices are numbered from 0

void build_the_subtree_rooted_at(int u, int p) {
  for (int v : g[u]) {
    if (v != p) {
      build_the_subtree_rooted_at(v, u);
      // ...
    }
  }
}

// reroot the whole tree at u whose parent was p.
void reroot(int u, int p) {
    // p lost a son u
    // u got a son p
    // modify u but DO NOT modify p
    // It suffices to calculate what p becomes if it lost the son u,
    // you don't have to actually modify p.
}

void dfs(int u, int p) {
    // compute f(u)
    // other things...
  for (int v : g[u]) {
    if (v != p) {
      reroot(v, u);
      dfs(v, u);
    }
  }
}

int main() {
  build_the_subtree_rooted_at(0, -1);
  dfs(0, -1);
}

解释

计算 \(f(u)\) 所需要的信息一般有两类,

  1. 依赖于 \(T\)\(u\) 的全局信息,这类信息一般可以在第一次扫描的过程中计算出来。
  2. 依赖于 \(T_{u}\) 的信息,把它记作 \(g(u) := g(T_u)\)\(g\) 是一个关于有根树的函数。

reroot(\(u\), \(p\)) 的作用就是计算 \(g(u)\)。计算 \(g(u)\) 所需要的信息可分成五类,

  1. \(g(1, u)\),在 \(g(u)\) 算出来之后即被 \(g(u)\) 取代。
  2. 关于 \(T_{1,u}\) 的除了 \(g(1, u)\) 之外的其他信息。
  3. 关于 \(T\) 的全局信息。
  4. \(g(p)\)
  5. 关于 \(T_{u,p}\) 的信息。

第 1, 2, 3 类信息都是在第一次扫描过程中算出来的,在第二次扫描过程中保持不变。在调用 reroot(\(u\), \(p\)) 之前 \(g(p)\) 已经算出来了,也保持不变。第 5 类信息是在函数 reroot 里由前 4 类信息计算出来的,只在计算 \(g(u)\) 时用到,所以不必保存。总而言之,在 reroot(\(u\), \(p\)) 所作的唯一更改就是用 \(g(u)\) 取代 \(g(1, u)\)。当然也可以不改变 \(g(1, u)\) 而把算出的 \(g(u)\) 另存他处。

Examples

CF1467E. Distinctive Roots in a Tree

提交:116070391

CF1092F. Tree with Maximum Cost

提交:116069700

POJ3585. Accumulation Degree

提交:31002137

posted @ 2021-01-17 16:52  Pat  阅读(225)  评论(0编辑  收藏  举报