Codeforces Round #629 (Div. 3) E. Tree Queries(LCA)

Codeforces Round #629 (Div. 3) E. Tree Queries

链接 https://codeforces.com/contest/1328/problem/E
题意 :
给你一棵以 1 为根节点的树,n-1条边,q次查询,问每次查询的 m个点是不是都以1为起点的同一条链上,或者与该链上一个点的距离为1.是输出yes
Codeforces Round #629 (Div. 3) E. Tree Queries(LCA)_第1张图片
例如 【1 3 2 9】 符合题意 而 【1 3 6 9】 不符合
思路:
我们只需要找到该数列中深度最大的点,对其他的点 i 找 最近公共祖先 fa 只要 都满足depth[ i ]-depth[ fa ]<= 1 即可。
关键在想到用最深的点和其他的点比较吧
代码

#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn=4e5+7;
int n,m,head[maxn],depth[maxn],fa[maxn][50],num=0;
int a[maxn];
struct node{
    int next,to;
};
struct node edge[maxn];
void add(int u,int v){
     edge[num].next=head[u];
     edge[num].to=v;
     head[u]=num++;
}
void dfs(int u, int pre, int d){
    fa[u][0] = pre, depth[u] = d;
    for(int i = head[u]; i != -1; i = edge[i].next){
        int to = edge[i].to;
        if(to != pre) dfs(to, u, d + 1);
    }
}
void init(int root){
    dfs(root, -1, 0);
    for(int j = 0; (1 << (j + 1)) < n; j++){
        for(int i = 1; i <= n; i++){
            if(fa[i][j] < 0) fa[i][j + 1] = -1;
            else fa[i][j + 1] = fa[fa[i][j]][j];
        }
    }
}
int LCA(int u, int v){
    if(depth[u] > depth[v]) swap(u, v);
    int temp = depth[v] - depth[u];
    for(int i = 0; (1 << i) <= temp; i++){
        if((1 << i) & temp) v = fa[v][i];
   }
    if(v == u) return u;
    for(int i = log(n*1.0)/log(2.0); i >= 0; i--){
        if(fa[u][i] != fa[v][i]){
            u = fa[u][i], v = fa[v][i];
        }
    }
    return fa[u][0];
}
int main (){
    memset(head,-1,sizeof(head));
    int u,v,root,k;
    cin>>n>>k;
    for(int i=0;i<n-1;i++){
        scanf("%d%d",&u,&v);
        add(u,v);
        add(v,u);
 
    }
    init(1);
    while(k--){
         int m,pos=1,flag=1;
         cin>>m;
         for(int i=0;i<m;i++){
            scanf("%d",&a[i]);
            if(depth[a[i]]>depth[pos]) pos=a[i];
         }
         for(int i=0;i<m;i++){
            int l=LCA(pos,a[i]);
            if(abs(depth[l]-depth[a[i]])>1){
                flag=0;
                break;
            }
         }
         if(flag) printf ("YES\n");
         else printf ("NO\n");
    }
}

忘记开两倍空间 wa 了好几发。

你可能感兴趣的:(Codeforces Round #629 (Div. 3) E. Tree Queries(LCA))