276 字
1 分钟
竞赛算法(6) 树上问题
树的dfs
完美, 简洁, 易于理解. 以维护子树大小为例:
int siz[N];vector<int> adj[N]; // 邻接表存无向边
auto dfs = [&](auto&& self, int x, int p) { siz[x] = 1; for (const auto& y : adj[x]) { if (y == p) continue; self(self, y, x); siz[x] += siz[y]; }};
// 调用dfs(dfs, root, -1);LCA
倍增算法
在的时间内预处理, 在时间内查询.
constexpr int N = 2e5 + 50;constexpr int LOG = 20; // 2^18 约 26 万int up[N][LOG + 1];int depth[N];vector<int> adj[N];
// 预处理depth数组和up数组void dfs(int x, int p) { for (int i = 1; i <= LOG; i++) { up[x][i] = up[up[x][i - 1]][i - 1]; } for (const auto& y : adj[x]) { if (y == p) continue; depth[y] = depth[x] + 1; up[y][0] = x; dfs(y, x); }}
// 求lcaint getlca(int x, int y) { if (depth[x] < depth[y]) swap(x, y);
for (int i = LOG; i >= 0; i--) { if (depth[x] - (1 << i) >= depth[y]) { x = up[x][i]; } }
if (x == y) { return x; }
for (int i = LOG; i >= 0; i--) { if (up[x][i] != up[y][i]) { x = up[x][i]; y = up[y][i]; } } return up[x][0];}基于LCA求树上两点距离
int dist(int x, int y) { return depth[x] + depth[y] - 2 * depth[getlca(x, y)];} 竞赛算法(6) 树上问题
https://fuwari.vercel.app/posts/竞赛算法6-树上问题/