祖孙询问
此问题可以用 LCA 来解决,但是 LCA 的码量大,而且可能容易写挂,尤其是像我这种蒟蒻
如果卡时间的话有可能倍增/重链剖分 LCA 都要挂掉,这时候就是 DFS 序发挥作用的时候了。
拿一个计数器。在遍历到每一个节点的时候,我们在进入它的时候记录一下,在离开它的时候也记录一下,在记录完成后就得到了一个树的 DFS 序
代码如下:
/*
LOJ10135
https://loj.ac/p/10135
*/
#include <iostream>
#include <vector>
using namespace std;
const int maxn = 4e4 + 5;
int n, m, root;
vector<int> G[maxn];
int ti;
int in[maxn], out[maxn];
void dfs(int x) {
if(in[x] != 0) return;
in[x] = ++ti;
for(int to : G[x]) dfs(to);
out[x] = ++ti;
}
int ask(int x, int y) {
return in[x] < in[y] && in[y] < out[y] && out[y] < out[x];
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n;
for(int i = 1, u, v; i <= n; i++) {
cin >> u >> v;
if(v == -1) {
root = u;
continue;
}
G[u].push_back(v);
G[v].push_back(u);
}
dfs(root);
cin >> m;
for(int i = 1, u, v; i <= m; i++) {
cin >> u >> v;
if(ask(u, v)) cout << 1 << "\n";
else if(ask(v, u)) cout << 2 << "\n";
else cout << 0 << "\n";
}
return 0;
}
//106ms
与倍增 LCA 相比,快了些许
祖孙询问(LOJ10135)
https://vjudge.csgrandeur.cn/contest/584212#problem/D
*/
#include <iostream>
#include <vector>
using namespace std;
const int maxn = 4e4 + 5;
const int maxk = 20;
int n, root, m;
vector<int> G[maxn];
int fa[maxk][maxn];
int depth[maxn];
void dfs(int x, int f) {
fa[0][x] = f;
depth[x] = depth[f] + 1;
for (int i = 1; i < maxk; i++) {
fa[i][x] = fa[i - 1][fa[i - 1][x]];
}
for (auto to : G[x]) {
if (to == f)
continue;
dfs(to, x);
}
}
int LCA(int x, int y) {
if (depth[x] < depth[y])
swap(x, y);
for (int i = maxk - 1; i >= 0; i--) {
if (depth[fa[i][x]] >= depth[y])
x = fa[i][x];
}
if (x == y)
return x;
for (int i = maxk - 1; i >= 0; i--) {
if (fa[i][x] != fa[i][y]) {
x = fa[i][x];
y = fa[i][y];
}
}
return fa[0][x];
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n;
for(int i = 1, u, v; i <= n; i++) {
cin >> u >> v;
if(v == -1) {root = u; continue;}
G[u].push_back(v);
G[v].push_back(u);
}
cin >> m;
int x, y;
dfs(root, 0);
while(m--) {
cin >> x >> y;
int lca = LCA(x, y);
if(lca == x) cout << "1\n";
else if(lca == y) cout << "2\n";
else cout << "0\n";
}
}
//130ms
因为在使用 DFS 序解决问题时,它的查询是常数时间复杂度,所以说要快很多。
当然,DFS 序也可以用于LCA问题中,详见这篇文章。