【题意】
给一棵树,然后给m次询问,每次询问,k个点,问:“从根开始的一条路径”与k个点,每个点距离小于等于1。
问题转化:k个点的父节点是否都在一条从根节点开始的路径上。
【题解】
参考了别人的博客,利用dfs序,把搜索顺序排序,然后限制最初出现时间和最后出现时间,步步缩小范围,如果有不合法的直接输出答案即可。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<vector> 5 #include<algorithm> 6 #include<iostream> 7 using namespace std; 8 typedef long long ll ; 9 const ll mod = 998244353 ; 10 const int N = 2e6 + 10; 11 vector< int > G[N]; 12 int n , m , k ; 13 int a[N] ; 14 int L[N] , R[N] , Fa[N] ; 15 int tag = 0; 16 void dfs( int u , int father ){ 17 18 Fa[u] = father ; 19 L[u] = ++ tag ; 20 21 for( int i = 0 ; i < (int)(G[u].size());i++ ){ 22 int x = G[u][i] ; 23 if( x == father ) continue ; 24 dfs( x , u ); 25 } 26 R[u] = tag ; 27 } 28 bool cmp( int u , int v ){ 29 return L[u] < L[v] ; 30 } 31 int main() 32 { 33 scanf("%d%d",&n,&m); 34 for( int i = 0 ,u,v; i < n-1 ; i++ ){ 35 scanf("%d%d",&u,&v); 36 G[u].push_back( v ); 37 G[v].push_back( u ); 38 } 39 40 dfs( 1 , 1 ); 41 while( m-- ){ 42 scanf("%d",&k); 43 for( int i = 0 ; i < k ; i++ ){ 44 scanf("%d",&a[i]); 45 a[i] = Fa[a[i]]; 46 } 47 sort( a , a + k , cmp ); 48 int ML = 0 , MR = N ; 49 bool flag = true ; 50 for( int i = 0 ; i < k ; i++ ){ 51 if( ML <= L[a[i]] && R[a[i]] <= MR ){ 52 ML = L[a[i]]; 53 MR = R[a[i]]; 54 }else{ 55 flag = false ; 56 } 57 } 58 puts(flag?"YES":"NO"); 59 } 60 return 0 ; 61 } 62 /* 63 10 6 64 1 2 65 1 3 66 1 4 67 2 5 68 2 6 69 3 7 70 7 8 71 7 9 72 9 10 73 4 3 8 9 10 74 3 2 4 6 75 3 2 1 5 76 3 4 8 2 77 2 6 10 78 3 5 4 7 79 80 */