給出一棵1爲根,n個節點的樹,每次詢問\(k_i\) 個節點,問是否存在這樣一條路徑:c++
因爲是從根出發的路徑,因此spa
這樣咱們就把兩個條件統一了,轉化問題爲:code
是否存在一條從根出發的路徑,使全部點都在這條路徑上排序
根據從根出發的路徑的特色,咱們根據深度,從小到大排序,每次看後一個點是否在前一個節點的子樹中就能夠了it
判斷是否在子樹中是很是經典的dfs序應用問題,先dfs一遍求出dfs序便可class
#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"); } } }