title | documentation_of |
---|---|
Rerooting (全方位木 DP) |
./rerooting.hpp |
- ここに記述する内容はリンク [1] で説明されていることとほぼ同等.
- 木の各頂点・各辺になんらかのデータ構造が載っている.
- 根付き木について,各頂点
を根とする部分木に対して計算される Subtree
型の情報をとする.また,各辺 が持つ Edge
型の情報をとする. -
は を満たす.ここで は の子の頂点たち. -
は の子 について Children
型の情報を計算する関数. -
は Children
型の引数をもとに頂点 における Subtree
型の情報を計算する関数. -
は任意個の Children
型の引数の積を計算する関数. -
には結合法則が成立しなければならない.また, Children
型の単位元をe()
とする.
-
- 以上のような性質を満たすデータ構造を考えたとき,本ライブラリは森の各頂点
を根とみなしたときの連結成分に関する の値を全ての について線形時間で計算する.
vector<int> inD;
struct Subtree {
bool exist;
int oneway, round;
};
struct Children {
bool exist;
int oneway, round;
};
Children rake(Children x, Children y) {
if (!x.exist) return y;
if (!y.exist) return x;
return Children{true, min(x.oneway + y.round, y.oneway + x.round), x.round + y.round};
}
Children add_edge(Subtree x, int, tuple<>) {
if (!x.exist) return {false, 0, 0};
return {true, x.oneway + 1, x.round + 2};
}
Subtree add_vertex(Children x, int v) {
if (x.exist) return {true, x.oneway, x.round};
return {inD[v], 0, 0};
return {false, 0, 0};
}
Children e() { return {false, 0, 0}; }
vector<vector<pair<int, tuple<>>>> to;
rerooting<tuple<>, Subtree, Children, rake, add_edge, add_vertex, e> tree(to);
tree.run();
for (auto x : tree.dpall) cout << x.oneway << '\n';
また,メソッド get_subtree(int root, int par)
によって,木を頂点 par
(par
が root
)を根とした根付き木として見た場合の頂点 root
を根とする部分木の情報が取得できる.
int u, v; // u-v 間に辺が存在
Subtree s1 = tree.get_subtree(u, v);