1 条题解
-
0
#include <bits/stdc++.h> using namespace std; const int MAXN = 40000; const int MAXM = 40000; int n, q, root; // 点数、询问个数、根节点 vector<int> e[MAXN + 5]; // 存树 int fa[MAXN + 5]; int maxDep, dep[MAXN + 5]; void dfs(int u, int father) { fa[u] = father; for (int i = 0; i < e[u].size(); i++) { int v = e[u][i]; if (v == father) continue; dep[v] = dep[u] + 1; maxDep = max(maxDep, dep[v]); dfs(v, u); } } int lg2[MAXN + 5]; // 替代 log2(i) int dp[MAXN][35]; // i号点的 2^j 层祖先 int lca(int u, int v) { if (dep[u] > dep[v]) swap(u, v); // 让u的高度不低于v if (u == v) return u; // 把 v 提到与 u 同样高度 for (int j = lg2[n]; j >= 0; j--) if ((1 << j) <= dep[v] - dep[u]) { v = dp[v][j]; } if (u == v) return u; // 找lca for (int j = lg2[n]; j >= 0; j--) if (dp[v][j] != dp[u][j]) { v = dp[v][j], u = dp[u][j]; } return dp[u][0]; } int main() { ios::sync_with_stdio(false); cin.tie(0); // 输入 cin >> n; for (int i = 1; i <= n; i++) { int u, v; cin >> u >> v; fa[u] = fa[v] = -1; if (v == -1) root = u; else { e[u].push_back(v); e[v].push_back(u); } } // 预处理:最大层数 maxDep、每个点的深度、记录父节点、log2[]、dp数组 dep[root] = 1; maxDep = 1; dfs(root, 0); lg2[1] = 0; for (int i = 2; i <= n; i++) // i == 2^(log2(i-1)+1) if (i == (1 << (lg2[i - 1] + 1))) lg2[i] = lg2[i - 1] + 1; else lg2[i] = lg2[i - 1]; for (int j = 0; j <= lg2[n]; j++) { for (int i = 1; i <= MAXN; i++) { if (fa[i] == -1) continue; // 求解 dp[i][j] if (j == 0) dp[i][j] = fa[i]; else dp[i][j] = dp[dp[i][j - 1]][j - 1]; } } // q 次询问 cin >> q; while (q--) { int u, v; cin >> u >> v; // 求 lca(u,v) int x = lca(u, v); if (x == u) cout << 1 << "\n"; else if (x == v) cout << 2 << "\n"; else cout << 0 << "\n"; } return 0; }
- 1
信息
- ID
- 787
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 4
- 标签
- 递交数
- 23
- 已通过
- 17
- 上传者