Codefroces 1328E Tree Querie(dfs序)

huaqinglv發表於2021-01-02

Codefroces 1328E Tree Querie

題目

給出一棵1為根,n個節點的樹,每次詢問\(k_i\) 個節點,問是否存在這樣一條路徑:

  • 從根出發,且每個節點在這條路徑上或者距離路徑的距離為1

題解

由於是從根出發的路徑,所以

  1. 距離這條路徑的距離為1=這個點的父親在路徑上
  2. 本身就在根出發的這條路徑上,當然這個點的父親也在路徑上

這樣我們就把兩個條件統一了,轉化問題為:

是否存在一條從根出發的路徑,使所有點都在這條路徑上

根據從根出發的路徑的特點,我們根據深度,從小到大排序,每次看後一個點是否在前一個節點的子樹中就可以了

判斷是否在子樹中是非常經典的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");
		}
	} 
}

相關文章