【DFS序】【CF-1328E】Tree Queries

【题意】

  给一棵树,然后给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  */
View Code

猜你喜欢

转载自www.cnblogs.com/Osea/p/12603426.html
今日推荐