CF1328E-Tree Queries(补) (dfs序)
题目链接:
https://codeforces.com/contest/1328/problem/E
思路:
题目大意就是问你从顶点到另一个点u,是否存在一条链,满足询问中的每个点都在
链上或者点的父节点在链上,首先我们可以发现深度最深的那个点max肯定是在链中的,
那么接下来我们只需要将每个点和他的父节点跟这个max点进行比较即可。如果该点跟max点
在一条链上,那么max点肯定在该点的子树中,那么问题转化为如何判断max点是否在该点的
子树中,我们可以用dfs序来判断。
代码:
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int MAXN=2e5+5; const ll INF=3e18; int n,m,k; vector<int>v[MAXN]; int a[MAXN],dep[MAXN],l[MAXN],r[MAXN],fa[MAXN],cnt; void dfs(int u) { l[u]=++cnt; for(int i=0; i<v[u].size(); i++) { int nxt=v[u][i]; if(nxt==fa[u]) continue; dep[nxt]=dep[u]+1; fa[nxt]=u; dfs(nxt); } r[u]=cnt; } bool ok(int x,int y) { return l[x]<=l[y]&&r[x]>=l[y]; } bool check(int u) { for(int i=1; i<=k; i++) { if(!ok(a[i],u)&&!ok(fa[a[i]],u)) return false; } return true; } int main() { ios::sync_with_stdio(false); cin.tie(0); cin>>n>>m; for(int i=1; i<=n-1; i++) { int x,y; cin>>x>>y; v[x].push_back(y); v[y].push_back(x); } dep[1]=1; dfs(1); while(m--) { cin>>k; int max_=0,u=0; for(int i=1; i<=k; i++) { cin>>a[i]; if(dep[a[i]]>max_) { max_=dep[a[i]]; u=a[i]; } } //cout<<u<<endl; if(check(u)) cout<<"YES"<<endl; else cout<<"NO"<<endl; } return 0; }