77#include < utility>
88#include < vector>
99
10- // Heavy-Light Decomposition of trees
10+ // Heavy-light decomposition of trees (forest)
1111// Based on http://beet-aizu.hatenablog.com/entry/2017/12/12/235950
12- struct HeavyLightDecomposition {
12+ struct heavy_light_decomposition {
1313 int V;
1414 int k;
15- int nb_heavy_path;
1615 std::vector<std::vector<int >> e;
1716 std::vector<int > par; // par[i] = parent of vertex i (Default: -1)
1817 std::vector<int > depth; // depth[i] = distance between root and vertex i
1918 std::vector<int > subtree_sz; // subtree_sz[i] = size of subtree whose root is i
2019 std::vector<int > heavy_child; // heavy_child[i] = child of vertex i on heavy path (Default: -1)
2120 std::vector<int > tree_id; // tree_id[i] = id of tree vertex i belongs to
22- std::vector<int > aligned_id,
23- aligned_id_inv; // aligned_id[i] = aligned id for vertex i (consecutive on heavy edges)
21+ // subtree_begin[i] = aligned id for vertex i (consecutive on heavy edges)
22+ std::vector<int > subtree_begin, subtree_end;
23+ std::vector<int > vis_order; // vis_order[subtree_begin[i]] = i
2424 std::vector<int > head; // head[i] = id of vertex on heavy path of vertex i, nearest to root
25- std::vector< int > head_ids; // consist of head vertex id's
26- std::vector<int > heavy_path_id; // heavy_path_id[i] = heavy_path_id for vertex [i]
27-
28- HeavyLightDecomposition ( int sz = 0 )
29- : V(sz), k( 0 ), nb_heavy_path( 0 ), e(sz), par(sz), depth(sz), subtree_sz(sz), heavy_child(sz),
30- tree_id (sz, - 1 ), aligned_id(sz), aligned_id_inv(sz), head(sz), heavy_path_id(sz, - 1 ) {}
31- void add_edge ( int u, int v) {
32- e[u]. emplace_back (v );
33- e[v]. emplace_back (u);
25+
26+ heavy_light_decomposition ( int n, const std::vector<std::pair< int , int >> &edges)
27+ : V(n), k( 0 ), e(n), par(n), depth(n), subtree_sz(n), heavy_child(n), tree_id(n, - 1 ),
28+ subtree_begin (n), subtree_end(n), vis_order( 0 ), head(n) {
29+ for ( auto [u, v] : edges) {
30+ assert (u != v);
31+ e. at (u). emplace_back (v);
32+ e. at (v). emplace_back (u );
33+ }
3434 }
3535
36- void _build_dfs (int root) {
37- std::stack <std::pair<int , int >> st;
36+ void _build_dfs_1 (int root) {
37+ std::vector <std::pair<int , int >> st;
3838 par[root] = -1 ;
3939 depth[root] = 0 ;
40- st.emplace (root, 0 );
40+ st.emplace_back (root, 0 );
4141 while (!st.empty ()) {
42- int now = st.top ().first ;
43- int &i = st.top ().second ;
42+ int now = st.back ().first ;
43+ int &i = st.back ().second ;
4444 if (i < (int )e[now].size ()) {
4545 int nxt = e[now][i++];
4646 if (nxt == par[now]) continue ;
4747 par[nxt] = now;
4848 depth[nxt] = depth[now] + 1 ;
49- st.emplace (nxt, 0 );
49+ st.emplace_back (nxt, 0 );
5050 } else {
51- st.pop ();
51+ st.pop_back ();
5252 int max_sub_sz = 0 ;
5353 subtree_sz[now] = 1 ;
5454 heavy_child[now] = -1 ;
5555 for (auto nxt : e[now]) {
5656 if (nxt == par[now]) continue ;
5757 subtree_sz[now] += subtree_sz[nxt];
58- if (max_sub_sz < subtree_sz[nxt])
58+ if (max_sub_sz < subtree_sz[nxt]) {
5959 max_sub_sz = subtree_sz[nxt], heavy_child[now] = nxt;
60+ }
6061 }
6162 }
6263 }
6364 }
6465
65- void _build_bfs (int root, int tree_id_now) {
66- std::queue<int > q ({root});
67- while (!q.empty ()) {
68- int h = q.front ();
69- q.pop ();
70- head_ids.emplace_back (h);
71- for (int now = h; now != -1 ; now = heavy_child[now]) {
66+ void _build_dfs_2 (int now, int tree_id_now) {
67+ std::vector<std::pair<int , bool >> st;
68+ st.emplace_back (now, true );
69+ head[now] = now;
70+
71+ while (!st.empty ()) {
72+ auto [now, mode] = st.back ();
73+ st.pop_back ();
74+
75+ if (mode) {
7276 tree_id[now] = tree_id_now;
73- aligned_id[now] = k++;
74- aligned_id_inv[aligned_id[now]] = now;
75- heavy_path_id[now] = nb_heavy_path;
76- head[now] = h;
77- for (int nxt : e[now])
78- if (nxt != par[now] and nxt != heavy_child[now]) q.push (nxt);
77+ subtree_begin[now] = k++;
78+ vis_order.push_back (now);
79+
80+ st.emplace_back (now, false );
81+
82+ for (int nxt : e[now]) {
83+ if (nxt == par[now] or nxt == heavy_child[now]) continue ;
84+ head[nxt] = nxt;
85+ st.emplace_back (nxt, true );
86+ }
87+
88+ if (heavy_child[now] != -1 ) {
89+ head[heavy_child[now]] = head[now];
90+ st.emplace_back (heavy_child[now], true );
91+ }
92+ } else {
93+ subtree_end[now] = k;
7994 }
80- nb_heavy_path++;
8195 }
8296 }
8397
8498 void build (std::vector<int > roots = {0 }) {
8599 int tree_id_now = 0 ;
86- for (auto r : roots) _build_dfs (r), _build_bfs (r, tree_id_now++);
100+ for (int r : roots) {
101+ _build_dfs_1 (r);
102+ _build_dfs_2 (r, tree_id_now++);
103+ }
87104 }
88105
89106 template <class T > std::vector<T> segtree_rearrange (const std::vector<T> &data) const {
90107 assert (int (data.size ()) == V);
91108 std::vector<T> ret;
92- ret.reserve (V );
93- for (int i = 0 ; i < V; i++ ) ret.emplace_back (data[aligned_id_inv[i] ]);
109+ ret.reserve (vis_order. size () );
110+ for (int v : vis_order ) ret.emplace_back (data[v ]);
94111 return ret;
95112 }
96113
114+ void for_vertex (int u, const std::function<void (int )> &f) const { f (subtree_begin[u]); }
115+
97116 // query for vertices on path [u, v] (INCLUSIVE)
98117 void
99118 for_each_vertex (int u, int v, const std::function<void (int ancestor, int descendant)> &f) const {
100119 while (true ) {
101- if (aligned_id [u] > aligned_id [v]) std::swap (u, v);
102- f (std::max (aligned_id [head[v]], aligned_id [u]), aligned_id [v]);
120+ if (subtree_begin [u] > subtree_begin [v]) std::swap (u, v);
121+ f (std::max (subtree_begin [head[v]], subtree_begin [u]), subtree_begin [v]);
103122 if (head[u] == head[v]) break ;
104123 v = par[head[v]];
105124 }
@@ -112,7 +131,7 @@ struct HeavyLightDecomposition {
112131 const int lca = lowest_common_ancestor (u, v), dlca = depth[lca];
113132 while (u >= 0 and depth[u] > dlca) {
114133 const int p = (depth[head[u]] > dlca ? head[u] : lca);
115- fup (aligned_id [p] + (p == lca), aligned_id [u]), u = par[p];
134+ fup (subtree_begin [p] + (p == lca), subtree_begin [u]), u = par[p];
116135 }
117136 static std::vector<std::pair<int , int >> lrs;
118137 int sz = 0 ;
@@ -121,28 +140,33 @@ struct HeavyLightDecomposition {
121140 if (int (lrs.size ()) == sz) lrs.emplace_back (0 , 0 );
122141 lrs.at (sz++) = {p, v}, v = par.at (p);
123142 }
124- while (sz--) fdown (aligned_id [lrs.at (sz).first ], aligned_id [lrs.at (sz).second ]);
143+ while (sz--) fdown (subtree_begin [lrs.at (sz).first ], subtree_begin [lrs.at (sz).second ]);
125144 }
126145
127146 // query for edges on path [u, v]
128147 void for_each_edge (int u, int v, const std::function<void (int , int )> &f) const {
129148 while (true ) {
130- if (aligned_id [u] > aligned_id [v]) std::swap (u, v);
149+ if (subtree_begin [u] > subtree_begin [v]) std::swap (u, v);
131150 if (head[u] != head[v]) {
132- f (aligned_id [head[v]], aligned_id [v]);
151+ f (subtree_begin [head[v]], subtree_begin [v]);
133152 v = par[head[v]];
134153 } else {
135- if (u != v) f (aligned_id [u] + 1 , aligned_id [v]);
154+ if (u != v) f (subtree_begin [u] + 1 , subtree_begin [v]);
136155 break ;
137156 }
138157 }
139158 }
140159
160+ // query for vertices in subtree rooted at u
161+ void for_subtree (int u, const std::function<void (int , int )> &f) const {
162+ f (subtree_begin[u], subtree_end[u] - 1 );
163+ }
164+
141165 // lowest_common_ancestor: O(log V)
142166 int lowest_common_ancestor (int u, int v) const {
143167 assert (tree_id[u] == tree_id[v] and tree_id[u] >= 0 );
144168 while (true ) {
145- if (aligned_id [u] > aligned_id [v]) std::swap (u, v);
169+ if (subtree_begin [u] > subtree_begin [v]) std::swap (u, v);
146170 if (head[u] == head[v]) return u;
147171 v = par[head[v]];
148172 }
@@ -159,7 +183,7 @@ struct HeavyLightDecomposition {
159183 if (k < 0 ) return -1 ;
160184 while (v >= 0 ) {
161185 int h = head.at (v), len = depth.at (v) - depth.at (h);
162- if (k <= len) return aligned_id_inv .at (aligned_id .at (v) - k);
186+ if (k <= len) return vis_order .at (subtree_begin .at (v) - k);
163187 k -= len + 1 , v = par.at (h);
164188 }
165189 return -1 ;
0 commit comments