Codefroces 1328E Tree Querie(dfs序)
Codefroces 1328E Tree Querie
题目
给出一棵1为根,n个节点的树,每次询问\(k_i\) 个节点,问是否存在这样一条路径:
- 从根出发,且每个节点在这条路径上或者距离路径的距离为1
题解
由于是从根出发的路径,所以
- 距离这条路径的距离为1=这个点的父亲在路径上
- 本身就在根出发的这条路径上,当然这个点的父亲也在路径上
这样我们就把两个条件统一了,转化问题为:
是否存在一条从根出发的路径,使所有点都在这条路径上
根据从根出发的路径的特点,我们根据深度,从小到大排序,每次看后一个点是否在前一个节点的子树中就可以了
判断是否在子树中是非常经典的dfs序应用问题,先dfs一遍求出dfs序即可
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+100;
int head[maxn],cnt,vis[maxn],dep[maxn],L[maxn],R[maxn],xu,fa[maxn];
struct E
{
int nxt,to;
}edge[maxn*2+10];
struct P
{
int dep,id;
}a[maxn];
bool cmp(P x,P y)
{
return x.dep<y.dep;
}
void add_edge(int x,int y)
{
edge[++cnt].nxt=head[x];
edge[cnt].to=y;
head[x]=cnt;
}
void dfs(int x,int F)
{
L[x]=++xu;
for(int i=head[x];i;i=edge[i].nxt){
int v=edge[i].to;
if(v==F) continue;
dep[v]=dep[x]+1;
fa[v]=x;
dfs(v,x);
}
R[x]=xu;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<n;i++){
int x,y;
scanf("%d%d",&x,&y);
add_edge(x,y);
add_edge(y,x);
}
fa[1]=1;
dep[1]=1;
dfs(1,0);
for(int i=1;i<=m;i++){
int x;
scanf("%d",&x);
for(int j=1;j<=x;j++){
int y;
scanf("%d",&y);
a[j].id=fa[y];
a[j].dep=dep[a[j].id];
}
sort(a+1,a+x+1,cmp);
int Top=a[1].id;
int flag=1;
for(int j=2;j<=x;j++){
int v=a[j].id;
if(L[Top]<=L[v]&&L[v]<=R[Top]){
Top=v;
}
else{
flag=0;
break;
}
}
if(flag==1){
printf("YES\n");
}
else{
printf("NO\n");
}
}
}