[CF1328E] Tree Queries - LCA
Posted mollnn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CF1328E] Tree Queries - LCA相关的知识,希望对你有一定的参考价值。
给定一棵有根树,每次询问给定一个点集,问是否存在根到某点的链,使得点集中所有点到链的距离不大于 (1)。
Solution
将每次询问的结点按深度排序好,相邻的两个结点 (p,q) 一定满足 (d[p]-d[lca] le 1 or d[q]-d[lca] le 1),其中 (lca=lca(p,q))
必要性显然,充分性考虑让毛毛虫的茎一直往差值大的那边走即可
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 200005;
vector <int> g[N];
int n,m,t1,t2,t3,dep[N],fa[N][20];
void dfs(int p) {
for(int q:g[p]) {
if(dep[q]) continue;
dep[q]=dep[p]+1;
fa[q][0]=p;
dfs(q);
}
}
int lca(int p,int q) {
if(dep[p]<dep[q]) swap(p,q);
for(int i=18;i>=0;--i) if(dep[fa[p][i]]>=dep[q]) p=fa[p][i];
for(int i=18;i>=0;--i) if(fa[p][i]-fa[q][i]) p=fa[p][i],q=fa[q][i];
if(p-q) return fa[p][0];
else return p;
}
bool cmp(const int &p,const int &q) {
return dep[p]<dep[q];
}
signed main() {
ios::sync_with_stdio(false);
cin>>n>>m;
for(int i=1;i<n;i++) {
cin>>t1>>t2;
g[t1].push_back(t2);
g[t2].push_back(t1);
}
dep[1]=1;
dfs(1);
for(int i=1;i<=18;i++) {
for(int j=1;j<=n;j++) {
fa[j][i]=fa[fa[j][i-1]][i-1];
}
}
for(int i=1;i<=m;i++) {
int k;
cin>>k;
vector <int> vec;
for(int j=0;j<k;j++) {
int t;
cin>>t;
vec.push_back(t);
}
sort(vec.begin(),vec.end(),cmp);
int fg=1;
for(int j=1;j<k;j++) {
int p=vec[j],q=vec[j-1];
int l=lca(p,q);
if(dep[p]-dep[l]>1 && dep[q]-dep[l]>1) fg=0;
}
cout<<(fg?"YES":"NO")<<endl;
}
}
以上是关于[CF1328E] Tree Queries - LCA的主要内容,如果未能解决你的问题,请参考以下文章
=Tree Queries CodeForces - 1328E (LCA+思维)