给定一棵有根树,每次询问给定一个点集,问是否存在根到某点的链,使得点集中所有点到链的距离不大于 \(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;
}
}
原文地址:https://www.cnblogs.com/mollnn/p/12580436.html
时间: 2024-10-18 17:46:07