Skip to content

Commit 2290bd5

Browse files
committed
rename rerooting
1 parent c596b1f commit 2290bd5

File tree

4 files changed

+52
-51
lines changed

4 files changed

+52
-51
lines changed

tree/rerooting.hpp

Lines changed: 25 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,19 @@
88
// Reference:
99
// - https://atcoder.jp/contests/abc222/editorial/2749
1010
// - https://null-mn.hatenablog.com/entry/2020/04/14/124151
11-
template <class Edge, class St, class Ch, Ch (*merge)(Ch, Ch), Ch (*f)(St, int, Edge),
12-
St (*g)(Ch, int), Ch (*e)()>
11+
template <class Edge, class Subtree, class Children, Children (*rake)(Children, Children),
12+
Children (*add_edge)(Subtree, int, Edge), Subtree (*add_vertex)(Children, int),
13+
Children (*e)()>
1314
struct rerooting {
1415
int n_;
1516
std::vector<int> par, visited;
1617
std::vector<std::vector<std::pair<int, Edge>>> to;
17-
std::vector<St> dp_subtree;
18-
std::vector<St> dp_par;
19-
std::vector<St> dpall;
18+
std::vector<Subtree> dp_subtree;
19+
std::vector<Subtree> dp_par;
20+
std::vector<Subtree> dpall;
2021
rerooting(const std::vector<std::vector<std::pair<int, Edge>>> &to_)
2122
: n_(to_.size()), par(n_, -1), visited(n_, 0), to(to_) {
22-
for (int i = 0; i < n_; ++i) dp_subtree.push_back(g(e(), i));
23+
for (int i = 0; i < n_; ++i) dp_subtree.push_back(add_vertex(e(), i));
2324
dp_par = dpall = dp_subtree;
2425
}
2526

@@ -41,33 +42,33 @@ struct rerooting {
4142

4243
for (int t = int(visorder.size()) - 1; t >= 0; --t) {
4344
int now = visorder[t];
44-
Ch ch = e();
45+
Children ch = e();
4546
for (const auto &edge : to[now]) {
4647
int nxt = edge.first;
4748
if (nxt == par[now]) continue;
48-
ch = merge(ch, f(dp_subtree[nxt], nxt, edge.second));
49+
ch = rake(ch, add_edge(dp_subtree[nxt], nxt, edge.second));
4950
}
50-
dp_subtree[now] = g(ch, now);
51+
dp_subtree[now] = add_vertex(ch, now);
5152
}
5253

53-
std::vector<Ch> left;
54+
std::vector<Children> left;
5455
for (int now : visorder) {
5556
int m = int(to[now].size());
5657
left.assign(m + 1, e());
5758
for (int j = 0; j < m; j++) {
5859
int nxt = to[now][j].first;
59-
const St &st = (nxt == par[now] ? dp_par[now] : dp_subtree[nxt]);
60-
left[j + 1] = merge(left[j], f(st, nxt, to[now][j].second));
60+
const Subtree &st = (nxt == par[now] ? dp_par[now] : dp_subtree[nxt]);
61+
left[j + 1] = rake(left[j], add_edge(st, nxt, to[now][j].second));
6162
}
62-
dpall[now] = g(left.back(), now);
63+
dpall[now] = add_vertex(left.back(), now);
6364

64-
Ch rprod = e();
65+
Children rprod = e();
6566
for (int j = m - 1; j >= 0; --j) {
6667
int nxt = to[now][j].first;
67-
if (nxt != par[now]) dp_par[nxt] = g(merge(left[j], rprod), now);
68+
if (nxt != par[now]) dp_par[nxt] = add_vertex(rake(left[j], rprod), now);
6869

69-
const St &st = (nxt == par[now] ? dp_par[now] : dp_subtree[nxt]);
70-
rprod = merge(f(st, nxt, to[now][j].second), rprod);
70+
const Subtree &st = (nxt == par[now] ? dp_par[now] : dp_subtree[nxt]);
71+
rprod = rake(add_edge(st, nxt, to[now][j].second), rprod);
7172
}
7273
}
7374
}
@@ -78,7 +79,7 @@ struct rerooting {
7879
}
7980
}
8081

81-
const St &get_subtree(int root_, int par_) const {
82+
const Subtree &get_subtree(int root_, int par_) const {
8283
if (par_ < 0) return dpall.at(root_);
8384
if (par.at(root_) == par_) return dp_subtree.at(root_);
8485
if (par.at(par_) == root_) return dp_par.at(par_);
@@ -87,13 +88,13 @@ struct rerooting {
8788
};
8889
/* Template:
8990
struct Subtree {};
90-
struct Child {};
91+
struct Children {};
9192
struct Edge {};
92-
Child e() { return Child(); }
93-
Child merge(Child x, Child y) { return Child(); }
94-
Child f(Subtree x, int ch_id, Edge edge) { return Child(); }
95-
Subtree g(Child x, int v_id) { return Subtree(); }
93+
Children e() { return Children(); }
94+
Children rake(Children x, Children y) { return Children(); }
95+
Children add_edge(Subtree x, int ch_id, Edge edge) { return Children(); }
96+
Subtree add_vertex(Children x, int v_id) { return Subtree(); }
9697
9798
vector<vector<pair<int, Edge>>> to;
98-
rerooting<Edge, Subtree, Child, merge, f, g, e> tree(to);
99+
rerooting<Edge, Subtree, Children, rake, add_edge, add_vertex, e> tree(to);
99100
*/

tree/rerooting.md

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ documentation_of: ./rerooting.hpp
77

88
- ここに記述する内容はリンク [1] で説明されていることとほぼ同等.
99
- 木の各頂点・各辺になんらかのデータ構造が載っている.
10-
- 根付き木について,各頂点 $v$ を根とする部分木に対して計算される `St` 型の情報を $X_v$ とする.また,各辺 $uv$ が持つ `Edge` 型の情報を $e_{uv}$ とする.
11-
- $X_v$ は $X_v = g\left(\mathrm{merge}\left(f(X\_{c\_1}, c\_1, e\_{v c\_1}), \dots, f(X\_{c\_k}, c\_k, e\_{v c\_k})\right), v \right)$ を満たす.ここで $c\_1, \dots, c\_k$ は $v$ の子の頂点たち.
12-
- $f(X\_v, v, e\_{uv})$ は $u$ の子 $v$ について `Ch` 型の情報を計算する関数.
13-
- $\mathrm{merge}(y\_1, \dots, y\_k)$ は任意個の `Ch` 型の引数の積を計算する関数
14-
- $g(y, v)$ は `Ch` 型の引数 $y$ をもとに頂点 $v$ における `St` 型の情報を計算する関数
15-
- `Ch` 型には結合法則が成立しなければならない.また, `Ch` 型の単位元を `e()` とする.
10+
- 根付き木について,各頂点 $v$ を根とする部分木に対して計算される `Subtree` 型の情報を $X_v$ とする.また,各辺 $uv$ が持つ `Edge` 型の情報を $e_{uv}$ とする.
11+
- $X_v$ は $X_v = \mathrm{add\_vertex}\left(\mathrm{rake}\left(\mathrm{add\_edge}(X\_{c\_1}, c\_1, e\_{v c\_1}), \dots, \mathrm{add\_edge}(X\_{c\_k}, c\_k, e\_{v c\_k})\right), v \right)$ を満たす.ここで $c\_1, \dots, c\_k$ は $v$ の子の頂点たち.
12+
- $\mathrm{add\_edge}(X\_v, v, e\_{uv})$ は $u$ の子 $v$ について `Children` 型の情報を計算する関数.
13+
- $\mathrm{add\_vertex}(y, v)$ は `Children` 型の引数 $y$ をもとに頂点 $v$ における `Subtree` 型の情報を計算する関数
14+
- $\mathrm{rake}(y\_1, \dots, y\_k)$ は任意個の `Children` 型の引数の積を計算する関数
15+
- $\mathrm{rake}()$ には結合法則が成立しなければならない.また, `Children` 型の単位元を `e()` とする.
1616
- 以上のような性質を満たすデータ構造を考えたとき,本ライブラリは森の各頂点 $r$ を根とみなしたときの連結成分に関する $X_r$ の値を全ての $r$ について線形時間で計算する.
1717

1818
## 使用方法(例)
@@ -23,29 +23,29 @@ struct Subtree {
2323
bool exist;
2424
int oneway, round;
2525
};
26-
struct Child {
26+
struct Children {
2727
bool exist;
2828
int oneway, round;
2929
};
30-
Child merge(Child x, Child y) {
30+
Children rake(Children x, Children y) {
3131
if (!x.exist) return y;
3232
if (!y.exist) return x;
33-
return Child{true, min(x.oneway + y.round, y.oneway + x.round), x.round + y.round};
33+
return Children{true, min(x.oneway + y.round, y.oneway + x.round), x.round + y.round};
3434
}
35-
Child f(Subtree x, int, tuple<>) {
35+
Children add_edge(Subtree x, int, tuple<>) {
3636
if (!x.exist) return {false, 0, 0};
3737
return {true, x.oneway + 1, x.round + 2};
3838
}
39-
Subtree g(Child x, int v) {
39+
Subtree add_vertex(Children x, int v) {
4040
if (x.exist) return {true, x.oneway, x.round};
4141
return {inD[v], 0, 0};
4242
return {false, 0, 0};
4343
}
44-
Child e() { return {false, 0, 0}; }
44+
Children e() { return {false, 0, 0}; }
4545

4646

4747
vector<vector<pair<int, tuple<>>>> to;
48-
rerooting<tuple<>, Subtree, Child, merge, f, g, e> tree(to);
48+
rerooting<tuple<>, Subtree, Children, rake, add_edge, add_vertex, e> tree(to);
4949
tree.run();
5050
for (auto x : tree.dpall) cout << x.oneway << '\n';
5151
```

tree/test/rerooting.aoj1595.test.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,19 @@ using namespace std;
99
struct Subtree {
1010
int oneway, round;
1111
};
12-
struct Child {
12+
struct Children {
1313
int oneway, round;
1414
};
1515

16-
Child merge(Child x, Child y) {
17-
return Child{min(x.oneway + y.round, y.oneway + x.round), x.round + y.round};
16+
Children merge(Children x, Children y) {
17+
return Children{min(x.oneway + y.round, y.oneway + x.round), x.round + y.round};
1818
}
1919

20-
Child f(Subtree x, int, tuple<>) { return {x.oneway + 1, x.round + 2}; }
20+
Children add_edge(Subtree x, int, tuple<>) { return {x.oneway + 1, x.round + 2}; }
2121

22-
Subtree g(Child x, int) { return {x.oneway, x.round}; }
22+
Subtree add_vertex(Children x, int) { return {x.oneway, x.round}; }
2323

24-
Child e() { return {0, 0}; }
24+
Children e() { return {0, 0}; }
2525

2626
int main() {
2727
cin.tie(nullptr), ios::sync_with_stdio(false);
@@ -34,7 +34,7 @@ int main() {
3434
--u, --v;
3535
to[u].push_back({v, {}}), to[v].push_back({u, {}});
3636
}
37-
rerooting<tuple<>, Subtree, Child, merge, f, g, e> tree(to);
37+
rerooting<tuple<>, Subtree, Children, merge, add_edge, add_vertex, e> tree(to);
3838
tree.run();
3939
for (auto x : tree.dpall) cout << x.oneway << '\n';
4040
}

tree/test/rerooting.yuki1718.test.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,24 @@ struct Subtree {
1111
bool exist;
1212
int oneway, round;
1313
};
14-
struct Child {
14+
struct Children {
1515
bool exist;
1616
int oneway, round;
1717
};
18-
Child e() { return {false, 0, 0}; }
18+
Children e() { return {false, 0, 0}; }
1919

20-
Child merge(Child x, Child y) {
20+
Children merge(Children x, Children y) {
2121
if (!x.exist) return y;
2222
if (!y.exist) return x;
23-
return Child{true, min(x.oneway + y.round, y.oneway + x.round), x.round + y.round};
23+
return Children{true, min(x.oneway + y.round, y.oneway + x.round), x.round + y.round};
2424
}
2525

26-
Child f(Subtree x, int, tuple<>) {
26+
Children add_edge(Subtree x, int, tuple<>) {
2727
if (!x.exist) return e();
2828
return {true, x.oneway + 1, x.round + 2};
2929
}
3030

31-
Subtree g(Child x, int v) {
31+
Subtree add_vertex(Children x, int v) {
3232
if (x.exist or inD[v]) return {true, x.oneway, x.round};
3333
return {false, 0, 0};
3434
}
@@ -52,7 +52,7 @@ int main() {
5252
cin >> d;
5353
inD[d - 1] = 1;
5454
}
55-
rerooting<tuple<>, Subtree, Child, merge, f, g, e> tree(to);
55+
rerooting<tuple<>, Subtree, Children, merge, add_edge, add_vertex, e> tree(to);
5656
tree.run();
5757
for (auto x : tree.dpall) cout << x.oneway << '\n';
5858
}

0 commit comments

Comments
 (0)