This documentation is automatically generated by online-judge-tools/verification-helper
#define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ITP1_1_A"
#include <cassert>
#include <iostream>
#include <random>
#include <utility>
#include <vector>
#include "graph/heavy_light_decomposition.hpp"
constexpr long long MOD = 998244353;
void stress(std::mt19937 &rng) {
const int N = 1 + rng() % 40;
const int root = rng() % N;
heavy_light_decomposition hld(N, root);
std::vector<std::vector<int>> g(N);
for (int v = 1; v < N; v++) {
int p = rng() % v;
hld.add_edge(v, p);
g[v].push_back(p);
g[p].push_back(v);
}
hld.build();
std::vector<int> par(N, -1), dep(N, 0);
auto dfs = [&](auto dfs, int v, int p) -> void {
for (int c : g[v]) {
if (c == p) continue;
par[c] = v;
dep[c] = dep[v] + 1;
dfs(dfs, c, v);
}
};
dfs(dfs, root, -1);
for (int i = 0; i + 1 < N; i++) {
// i 番目の辺は (i + 1, p) で p < i + 1
int v = i + 1, p = -1;
for (int x : g[v]) if (x < v) p = x;
int child = par[v] == p ? v : p;
assert(hld.edge_index(i) == hld.index(child));
}
auto naive_path = [&](int u, int v) {
std::vector<int> a, b;
while (u != v) {
if (dep[u] >= dep[v]) {
a.push_back(u);
u = par[u];
} else {
b.push_back(v);
v = par[v];
}
}
a.push_back(u);
a.insert(a.end(), b.rbegin(), b.rend());
return a;
};
std::vector<long long> w(N), fa(N), fb(N);
for (int v = 0; v < N; v++) {
w[v] = rng() % 100;
fa[v] = rng() % MOD;
fb[v] = rng() % MOD;
}
for (int i = 0; i < N; i++) {
assert(hld.vertex(hld.index(i)) == i);
assert(hld.depth(i) == dep[i]);
assert(hld.parent(i) == par[i]);
}
for (int q = 0; q < 300; q++) {
int u = rng() % N, v = rng() % N;
std::vector<int> path = naive_path(u, v);
int l = -1;
for (int x : path) {
if (l == -1 || dep[x] < dep[l]) l = x;
}
assert(hld.lca(u, v) == l);
assert(hld.dist(u, v) == (int)path.size() - 1);
int k = rng() % (path.size() + 2) - 1;
if (0 <= k && k < (int)path.size()) {
assert(hld.jump(u, v, k) == path[k]);
} else {
assert(hld.jump(u, v, k) == -1);
}
{
int x = rng() % N;
bool on = false;
for (int y : path) on |= (y == x);
assert(hld.on_path(u, v, x) == on);
bool sub = false;
for (int y = x; y != -1; y = par[y]) sub |= (y == u);
assert(hld.in_subtree(u, x) == sub);
int kk = rng() % (dep[x] + 2) - 1;
int y = x;
for (int i = 0; i < kk && y != -1; i++) y = par[y];
assert(hld.la(x, kk) == (kk < 0 ? -1 : y));
}
{
long long sv = 0, se = 0;
for (int x : path) sv += w[x];
for (int x : path) {
if (x != l) se += w[x];
}
long long hv = 0, he = 0;
hld.for_each_vertex(u, v, [&](int a, int b) {
assert(a < b);
for (int i = a; i < b; i++) hv += w[hld.vertex(i)];
});
hld.for_each_edge(u, v, [&](int a, int b) {
assert(a < b);
for (int i = a; i < b; i++) he += w[hld.vertex(i)];
});
assert(hv == sv);
assert(he == se);
}
{
long long na = 1, nb = 0;
for (int x : path) {
nb = (fa[x] * nb + fb[x]) % MOD;
na = fa[x] * na % MOD;
}
long long nea = 1, neb = 0;
for (int x : path) {
if (x == l) continue;
neb = (fa[x] * neb + fb[x]) % MOD;
nea = fa[x] * nea % MOD;
}
auto apply = [&](long long &ca, long long &cb, int a, int b) {
if (a < b) {
for (int i = a; i < b; i++) {
int x = hld.vertex(i);
cb = (fa[x] * cb + fb[x]) % MOD;
ca = fa[x] * ca % MOD;
}
} else {
for (int i = a - 1; i >= b; i--) {
int x = hld.vertex(i);
cb = (fa[x] * cb + fb[x]) % MOD;
ca = fa[x] * ca % MOD;
}
}
};
long long ha = 1, hb = 0;
hld.for_each_vertex_noncommutative(
u, v, [&](int a, int b) { apply(ha, hb, a, b); });
assert(ha == na && hb == nb);
long long hea = 1, heb = 0;
hld.for_each_edge_noncommutative(
u, v, [&](int a, int b) { apply(hea, heb, a, b); });
assert(hea == nea && heb == neb);
}
{
long long sv = 0, se = 0;
for (int x = 0; x < N; x++) {
bool sub = false;
for (int y = x; y != -1; y = par[y]) sub |= (y == u);
if (!sub) continue;
sv += w[x];
if (x != u) se += w[x];
}
long long hv = 0, he = 0;
hld.for_each_vertex_in_subtree(u, [&](int a, int b) {
for (int i = a; i < b; i++) hv += w[hld.vertex(i)];
});
hld.for_each_edge_in_subtree(u, [&](int a, int b) {
assert(a < b);
for (int i = a; i < b; i++) he += w[hld.vertex(i)];
});
assert(hv == sv);
assert(he == se);
auto [a, b] = hld.subtree(u);
assert(a == hld.index(u) && b - a == 1 + [&] {
int c = 0;
for (int x = 0; x < N; x++) {
bool sub = false;
for (int y = par[x]; y != -1; y = par[y]) sub |= (y == u);
c += sub;
}
return c;
}());
}
}
}
int main() {
std::mt19937 rng(7959);
for (int trial = 0; trial < 100; trial++) stress(rng);
std::cout << "Hello World" << std::endl;
return 0;
}#line 1 "test/unit/heavy_light_decomposition.test.cpp"
#define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=ITP1_1_A"
#include <cassert>
#include <iostream>
#include <random>
#include <utility>
#include <vector>
#line 2 "graph/heavy_light_decomposition.hpp"
#include <algorithm>
#line 6 "graph/heavy_light_decomposition.hpp"
struct heavy_light_decomposition {
public:
heavy_light_decomposition() {
}
heavy_light_decomposition(int n, int root = 0)
: _n(n),
_root(root),
g(n),
sub(n),
dep(n),
par(n),
heavy(n, -1),
head(n),
in(n),
out(n),
rev(n) {
}
void add_edge(int u, int v) {
assert(0 <= u && u < _n);
assert(0 <= v && v < _n);
g[u].push_back(v);
g[v].push_back(u);
edges.emplace_back(u, v);
}
void build() {
par[_root] = -1;
dep[_root] = 0;
std::vector<int> order, st = {_root};
order.reserve(_n);
while (!st.empty()) {
int v = st.back();
st.pop_back();
order.push_back(v);
for (int c : g[v]) {
if (c == par[v]) continue;
par[c] = v;
dep[c] = dep[v] + 1;
st.push_back(c);
}
}
for (int i = _n - 1; i >= 0; i--) {
int v = order[i], p = par[v];
sub[v]++;
if (p == -1) continue;
sub[p] += sub[v];
if (heavy[p] == -1 || sub[v] > sub[heavy[p]]) heavy[p] = v;
}
int t = 0;
head[_root] = _root;
st = {_root};
while (!st.empty()) {
int v = st.back();
st.pop_back();
in[v] = t++;
rev[in[v]] = v;
out[v] = in[v] + sub[v];
for (int c : g[v]) {
if (c == par[v] || c == heavy[v]) continue;
head[c] = c;
st.push_back(c);
}
if (heavy[v] != -1) {
head[heavy[v]] = head[v];
st.push_back(heavy[v]);
}
}
}
int index(int v) const {
return in[v];
}
int vertex(int i) const {
return rev[i];
}
std::pair<int, int> subtree(int v) const {
return {in[v], out[v]};
}
int edge_index(int i) const {
assert(0 <= i && i < (int)edges.size());
auto [u, v] = edges[i];
return in[par[u] == v ? u : v];
}
int depth(int v) const {
return dep[v];
}
int parent(int v) const {
return par[v];
}
int head_of(int v) const {
return head[v];
}
int lca(int u, int v) const {
while (head[u] != head[v]) {
if (dep[head[u]] < dep[head[v]]) std::swap(u, v);
u = par[head[u]];
}
return dep[u] < dep[v] ? u : v;
}
int lca(int u, int v, int r) const {
return lca(u, v) ^ lca(v, r) ^ lca(r, u);
}
int dist(int u, int v) const {
return dep[u] + dep[v] - 2 * dep[lca(u, v)];
}
int la(int v, int k) const {
if (k < 0 || dep[v] < k) return -1;
while (dep[v] - dep[head[v]] < k) {
k -= dep[v] - dep[head[v]] + 1;
v = par[head[v]];
}
return rev[in[v] - k];
}
int jump(int s, int t, int k) const {
int l = lca(s, t);
int d = dep[s] + dep[t] - 2 * dep[l];
if (k < 0 || d < k) return -1;
if (k <= dep[s] - dep[l]) return la(s, k);
return la(t, d - k);
}
bool in_subtree(int u, int v) const {
return in[u] <= in[v] && in[v] < out[u];
}
bool on_path(int s, int t, int x) const {
return dist(s, x) + dist(x, t) == dist(s, t);
}
template <typename F>
void for_each_vertex(int u, int v, const F& f) const {
for_each(u, v, false, f);
}
template <typename F>
void for_each_edge(int u, int v, const F& f) const {
for_each(u, v, true, f);
}
template <typename F>
void for_each_vertex_noncommutative(int u, int v, const F& f) const {
for_each_noncommutative(u, v, false, f);
}
template <typename F>
void for_each_edge_noncommutative(int u, int v, const F& f) const {
for_each_noncommutative(u, v, true, f);
}
template <typename F>
void for_each_vertex_in_subtree(int v, const F& f) const {
f(in[v], out[v]);
}
template <typename F>
void for_each_edge_in_subtree(int v, const F& f) const {
if (in[v] + 1 < out[v]) f(in[v] + 1, out[v]);
}
private:
int _n, _root;
std::vector<std::vector<int>> g;
std::vector<std::pair<int, int>> edges;
std::vector<int> sub, dep, par, heavy, head, in, out, rev;
template <typename F>
void for_each(int u, int v, bool edge, const F& f) const {
while (head[u] != head[v]) {
if (dep[head[u]] < dep[head[v]]) std::swap(u, v);
f(in[head[u]], in[u] + 1);
u = par[head[u]];
}
if (dep[u] > dep[v]) std::swap(u, v);
if (in[u] + edge < in[v] + 1) f(in[u] + edge, in[v] + 1);
}
template <typename F>
void for_each_noncommutative(int u, int v, bool edge, const F& f) const {
std::vector<std::pair<int, int>> down;
while (head[u] != head[v]) {
if (dep[head[u]] >= dep[head[v]]) {
f(in[u] + 1, in[head[u]]);
u = par[head[u]];
} else {
down.emplace_back(in[head[v]], in[v] + 1);
v = par[head[v]];
}
}
if (dep[u] > dep[v]) {
if (in[v] + edge < in[u] + 1) f(in[u] + 1, in[v] + edge);
} else {
if (in[u] + edge < in[v] + 1) f(in[u] + edge, in[v] + 1);
}
for (auto it = down.rbegin(); it != down.rend(); it++) {
f(it->first, it->second);
}
}
};
#line 9 "test/unit/heavy_light_decomposition.test.cpp"
constexpr long long MOD = 998244353;
void stress(std::mt19937 &rng) {
const int N = 1 + rng() % 40;
const int root = rng() % N;
heavy_light_decomposition hld(N, root);
std::vector<std::vector<int>> g(N);
for (int v = 1; v < N; v++) {
int p = rng() % v;
hld.add_edge(v, p);
g[v].push_back(p);
g[p].push_back(v);
}
hld.build();
std::vector<int> par(N, -1), dep(N, 0);
auto dfs = [&](auto dfs, int v, int p) -> void {
for (int c : g[v]) {
if (c == p) continue;
par[c] = v;
dep[c] = dep[v] + 1;
dfs(dfs, c, v);
}
};
dfs(dfs, root, -1);
for (int i = 0; i + 1 < N; i++) {
// i 番目の辺は (i + 1, p) で p < i + 1
int v = i + 1, p = -1;
for (int x : g[v]) if (x < v) p = x;
int child = par[v] == p ? v : p;
assert(hld.edge_index(i) == hld.index(child));
}
auto naive_path = [&](int u, int v) {
std::vector<int> a, b;
while (u != v) {
if (dep[u] >= dep[v]) {
a.push_back(u);
u = par[u];
} else {
b.push_back(v);
v = par[v];
}
}
a.push_back(u);
a.insert(a.end(), b.rbegin(), b.rend());
return a;
};
std::vector<long long> w(N), fa(N), fb(N);
for (int v = 0; v < N; v++) {
w[v] = rng() % 100;
fa[v] = rng() % MOD;
fb[v] = rng() % MOD;
}
for (int i = 0; i < N; i++) {
assert(hld.vertex(hld.index(i)) == i);
assert(hld.depth(i) == dep[i]);
assert(hld.parent(i) == par[i]);
}
for (int q = 0; q < 300; q++) {
int u = rng() % N, v = rng() % N;
std::vector<int> path = naive_path(u, v);
int l = -1;
for (int x : path) {
if (l == -1 || dep[x] < dep[l]) l = x;
}
assert(hld.lca(u, v) == l);
assert(hld.dist(u, v) == (int)path.size() - 1);
int k = rng() % (path.size() + 2) - 1;
if (0 <= k && k < (int)path.size()) {
assert(hld.jump(u, v, k) == path[k]);
} else {
assert(hld.jump(u, v, k) == -1);
}
{
int x = rng() % N;
bool on = false;
for (int y : path) on |= (y == x);
assert(hld.on_path(u, v, x) == on);
bool sub = false;
for (int y = x; y != -1; y = par[y]) sub |= (y == u);
assert(hld.in_subtree(u, x) == sub);
int kk = rng() % (dep[x] + 2) - 1;
int y = x;
for (int i = 0; i < kk && y != -1; i++) y = par[y];
assert(hld.la(x, kk) == (kk < 0 ? -1 : y));
}
{
long long sv = 0, se = 0;
for (int x : path) sv += w[x];
for (int x : path) {
if (x != l) se += w[x];
}
long long hv = 0, he = 0;
hld.for_each_vertex(u, v, [&](int a, int b) {
assert(a < b);
for (int i = a; i < b; i++) hv += w[hld.vertex(i)];
});
hld.for_each_edge(u, v, [&](int a, int b) {
assert(a < b);
for (int i = a; i < b; i++) he += w[hld.vertex(i)];
});
assert(hv == sv);
assert(he == se);
}
{
long long na = 1, nb = 0;
for (int x : path) {
nb = (fa[x] * nb + fb[x]) % MOD;
na = fa[x] * na % MOD;
}
long long nea = 1, neb = 0;
for (int x : path) {
if (x == l) continue;
neb = (fa[x] * neb + fb[x]) % MOD;
nea = fa[x] * nea % MOD;
}
auto apply = [&](long long &ca, long long &cb, int a, int b) {
if (a < b) {
for (int i = a; i < b; i++) {
int x = hld.vertex(i);
cb = (fa[x] * cb + fb[x]) % MOD;
ca = fa[x] * ca % MOD;
}
} else {
for (int i = a - 1; i >= b; i--) {
int x = hld.vertex(i);
cb = (fa[x] * cb + fb[x]) % MOD;
ca = fa[x] * ca % MOD;
}
}
};
long long ha = 1, hb = 0;
hld.for_each_vertex_noncommutative(
u, v, [&](int a, int b) { apply(ha, hb, a, b); });
assert(ha == na && hb == nb);
long long hea = 1, heb = 0;
hld.for_each_edge_noncommutative(
u, v, [&](int a, int b) { apply(hea, heb, a, b); });
assert(hea == nea && heb == neb);
}
{
long long sv = 0, se = 0;
for (int x = 0; x < N; x++) {
bool sub = false;
for (int y = x; y != -1; y = par[y]) sub |= (y == u);
if (!sub) continue;
sv += w[x];
if (x != u) se += w[x];
}
long long hv = 0, he = 0;
hld.for_each_vertex_in_subtree(u, [&](int a, int b) {
for (int i = a; i < b; i++) hv += w[hld.vertex(i)];
});
hld.for_each_edge_in_subtree(u, [&](int a, int b) {
assert(a < b);
for (int i = a; i < b; i++) he += w[hld.vertex(i)];
});
assert(hv == sv);
assert(he == se);
auto [a, b] = hld.subtree(u);
assert(a == hld.index(u) && b - a == 1 + [&] {
int c = 0;
for (int x = 0; x < N; x++) {
bool sub = false;
for (int y = par[x]; y != -1; y = par[y]) sub |= (y == u);
c += sub;
}
return c;
}());
}
}
}
int main() {
std::mt19937 rng(7959);
for (int trial = 0; trial < 100; trial++) stress(rng);
std::cout << "Hello World" << std::endl;
return 0;
}