题目链接
dfs序学习博客
解法:dfs预处理:求出每个节点的L-dfs序号、子树中最大dfs序号、fa[i] i的父节点
根据题意易得:合法条件 等价于 每个节点的父节点在一条直线上
按dfs序排序后,遍历(根到叶遍历),不断缩小当前子树【L,R】,若出现不在当前子树范围内,则不合法
#include<bits/stdc++.h> using namespace std; int n,m; vector<int> G[200005]; int v[200005]; int cnt=0; int vis[200005]; int L[200005],R[200005];// L R 该子树的序号范围 int fa[200005]; void dfs(int u,int fat) { fa[u]=fat; L[u]=++cnt; for(auto T : G[u]) { if(T!=fat) { dfs(T,u); } } R[u]=cnt; } int cmp(int a,int b) { return L[a]<L[b]; } int main() { scanf("%d%d",&n,&m); for(int i=0;i<n-1;i++) { int x,y; scanf("%d%d",&x,&y); G[x].push_back(y) ; G[y].push_back(x) ; } vis[1]=1; dfs(1,1); while(m--) { int k; scanf("%d",&k); for(int i=0;i<k;i++) { scanf("%d",&v[i]); v[i]=fa[v[i]]; } sort(v,v+k,cmp); int mxL=0,miR=200005; int flag=0; for(int i=0;i<k;i++) { if(L[v[i]]>=mxL&&R[v[i]]<=miR)//从上到下 不断缩小子树范围 { mxL=L[v[i]]; miR=R[v[i]]; } else// 该节点不在目前子树范围 非法 ! { flag=1; break; } } if(flag) { printf("NO\n"); } else { printf("YES\n"); } } }
E - Tree Queries (DFS序)
最新推荐文章于 2022-07-07 13:11:23 发布