CodeForces-1328E Tree Queries
Tree Queries
LCA 倍增 + 思维
所有的点到一条链的距离至多为 \(1\),代表他们的父节点一定都在同一条链上
根据这个,找到最深的点,然后判断所有的点和它是不是在同一个链:它与其他点的 LCA 都是等于其他点
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn = 2e5 + 10;
vector<int>gra[maxn];
int dep[maxn], fa[maxn][25];
void dfs(int now, int pre, int d)
{
dep[now] = d;
fa[now][0] = pre;
for(int nex : gra[now])
{
if(nex == pre) continue;
dfs(nex, now, d + 1);
}
}
void init(int n)
{
dfs(1, 1, 1);
for(int i=1; i<25; i++)
for(int j=1; j<=n; j++)
fa[j][i] = fa[fa[j][i-1]][i-1];
}
int LCA(int a, int b)
{
if(dep[a] < dep[b]) swap(a, b);
int dif = dep[a] - dep[b];
for(int i=24; i>=0; i--)
{
if(dif >= (1 << i))
{
dif -= 1 << i;
a = fa[a][i];
}
}
if(a == b) return a;
for(int i=24; i>=0; i--)
{
if(fa[a][i] != fa[b][i])
{
a = fa[a][i];
b = fa[b][i];
}
}
return fa[a][0];
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n, m;
cin >> n >> m;
for(int i=1; i<n; i++)
{
int a, b;
cin >> a >> b;
gra[a].push_back(b);
gra[b].push_back(a);
}
init(n);
while(m--)
{
int k;
cin >> k;
vector<int>p(k);
int dd = -1, pa = 0;
for(int i=0; i<k; i++)
{
cin >> p[i];
p[i] = fa[p[i]][0];
if(dep[p[i]] > dd)
{
dd = dep[p[i]];
pa = p[i];
}
}
int f = 1;
for(int i=0; i<k && f; i++)
{
if(LCA(pa, p[i]) != p[i])
f = 0;
}
if(f) cout << "YES\n";
else cout << "NO\n";
}
cout << endl;
return 0;
}
也可以用 \(dfs\) 序来判断是否在同一条链:找到 \(dfs\) 序最深的那个点,然后判断其他点是不是其祖先,如果都是证明是同一条链
时间复杂度 \(O(n + \sum k)\)
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn = 2e5 + 10;
vector<int>gra[maxn];
int dep[maxn], in[maxn], out[maxn], fa[maxn];
int tp = 0;
void dfs(int now, int pre, int d)
{
dep[now] = d;
in[now] = ++tp;
fa[now] = pre;
for(int nex : gra[now])
{
if(nex == pre) continue;
dfs(nex, now, d + 1);
}
out[now] = ++tp;
}
bool is_anc(int u, int v)
{
return in[u] <= in[v] && out[v] <= out[u];
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int n, m;
cin >> n >> m;
for(int i=1; i<n; i++)
{
int a, b;
cin >> a >> b;
gra[a].push_back(b);
gra[b].push_back(a);
}
dfs(1, 1, 1);
while(m--)
{
int k;
cin >> k;
vector<int>p(k);
int pb = -1;
for(int i=0; i<k; i++)
{
cin >> p[i];
p[i] = fa[p[i]];
if(pb == -1 || out[pb] > out[p[i]]) pb = p[i];
}
int f = 1;
for(int i=0; i<k && f; i++)
{
if(!is_anc(p[i], pb))
f = 0;
}
if(f) cout << "YES\n";
else cout << "NO\n";
}
cout << endl;
return 0;
}