1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
| struct HLD { int n; std::vector<int> siz, top, dep, parent, in, out, seq; std::vector<std::vector<int>> adj; int cur; HLD() {} HLD(int n) { init(n); } void init(int n) { this->n = n; siz.resize(n); top.resize(n); dep.resize(n); parent.resize(n); in.resize(n); out.resize(n); seq.resize(n); cur = 0; adj.assign(n, {}); } void addEdge(int u, int v) { adj[u].push_back(v); adj[v].push_back(u); } void work(int root = 0) { top[root] = root; dep[root] = 0; parent[root] = -1; dfs1(root); dfs2(root); } void dfs1(int u) { if (parent[u] != -1) { adj[u].erase(std::find(adj[u].begin(), adj[u].end(), parent[u])); } siz[u] = 1; for (auto &v : adj[u]) { parent[v] = u; dep[v] = dep[u] + 1; dfs1(v); siz[u] += siz[v]; if (siz[v] > siz[adj[u][0]]) { std::swap(v, adj[u][0]); } } } void dfs2(int u) { in[u] = cur++; seq[in[u]] = u; for (auto v : adj[u]) { top[v] = v == adj[u][0] ? top[u] : v; dfs2(v); } out[u] = cur; } int lca(int u, int v) { while (top[u] != top[v]) { if (dep[top[u]] > dep[top[v]]) { u = parent[top[u]]; } else { v = parent[top[v]]; } } return dep[u] < dep[v] ? u : v; } int dist(int u, int v) { return dep[u] + dep[v] - 2 * dep[lca(u, v)]; } int jump(int u, int k) { if (dep[u] < k) { return -1; } int d = dep[u] - k; while (dep[top[u]] > d) { u = parent[top[u]]; } return seq[in[u] - dep[u] + d]; } bool isAncester(int u, int v) { return in[u] <= in[v] && in[v] < out[u]; } int rootedParent(int u, int v) { std::swap(u, v); if (u == v) { return u; } if (!isAncester(u, v)) { return parent[u]; } auto it = std::upper_bound(adj[u].begin(), adj[u].end(), v, [&](int x, int y) { return in[x] < in[y]; }) - 1; return *it; } int rootedSize(int u, int v) { if (u == v) { return n; } if (!isAncester(v, u)) { return siz[v]; } return n - siz[rootedParent(u, v)]; } int rootedLca(int a, int b, int c) { return lca(a, b) ^ lca(b, c) ^ lca(c, a); } };
|