Codeforces Round #629E Tree Queries
You are given a rooted tree consisting of n vertices numbered from 1 to n. The root of the tree is a vertex number 1.
A tree is a connected undirected graph with n−1 edges.
You are given m queries. The i-th query consists of the set of ki distinct vertices vi[1],vi[2],…,vi[ki]. Your task is to say if there is a path from the root to some vertex u such that each of the given k vertices is either belongs to this path or has the distance 1 to some vertex of this path.
…
大概题意:能否在树上找到一条路径使得给出的k个结点在这条路径上或者到路径的距离为1
传送门:Tree Queries
思路分析:
找到给出的k个节点中最深的节点,若满足题意则k个结点中最深的结点和第i个结点的最近公共祖先为第i个祖先的父结点或者就是第i个结点本身。
代码实现:
#include<iostream>
#include<vector>
using namespace std;
const int MAX_N=2e5+5;
const int MAX_BIT=21;
vector<int>G[MAX_N];
int depth[MAX_N],father[MAX_N][MAX_BIT],lg[MAX_N];
int n;int num[MAX_N];
void dfs(int nowp,int fa){
depth[nowp]=depth[fa]+1;
father[nowp][0]=fa;
for(int i=1;i<=lg[depth[nowp]];++i)
father[nowp][i]=father[father[nowp][i-1]][i-1];
for(int i=0;i<G[nowp].size();++i){
if(G[nowp][i]==fa)continue;
else dfs(G[nowp][i],nowp);
}
}
int LCA(int u,int v){
if(depth[u]<depth[v])swap(u,v);
int dep=depth[u]-depth[v];
for(int i=0;i<MAX_BIT;++i)
if((dep>>i)&1)u=father[u][i];
if(u==v)return u;
for(int i=lg[depth[u]];i>=0;i--){
if(father[u][i]!=father[v][i]){
u=father[u][i];
v=father[v][i];
}
}
return father[u][0];
}
int main(){
lg[0]=-1;
for(int i=1;i<=MAX_N;++i)
lg[i]=lg[i>>1]+1;
int v,ask;
cin>>v>>ask;
for(int i=1;i<=v-1;++i){
int from,to;
cin>>from>>to;
G[from].push_back(to);
G[to].push_back(from);
}
dfs(1,0);
for(int i=1;i<=ask;++i){
cin>>n;
int maxdep=0,maxdep_v=0;
for(int i=1;i<=n;++i){
cin>>num[i];
if(depth[num[i]]>maxdep)maxdep=depth[num[i]],maxdep_v=num[i];
}
int update=1;
for(int i=1;i<=n;++i){
if(depth[LCA(maxdep_v,num[i])]-depth[num[i]]>1||depth[LCA(maxdep_v,num[i])]-depth[num[i]]<-1)update=0;
}
if(update)puts("YES");
else puts("NO");
}
return 0;
}