CF1328E-Tree Queries(补) (dfs序)

题目链接:

https://codeforces.com/contest/1328/problem/E

思路:

题目大意就是问你从顶点到另一个点u,是否存在一条链,满足询问中的每个点都在

链上或者点的父节点在链上,首先我们可以发现深度最深的那个点max肯定是在链中的,

那么接下来我们只需要将每个点和他的父节点跟这个max点进行比较即可。如果该点跟max点

在一条链上,那么max点肯定在该点的子树中,那么问题转化为如何判断max点是否在该点的

子树中,我们可以用dfs序来判断

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN=2e5+5;
const ll INF=3e18;
int n,m,k;
vector<int>v[MAXN];
int a[MAXN],dep[MAXN],l[MAXN],r[MAXN],fa[MAXN],cnt;
void dfs(int u)
{
    l[u]=++cnt;
    for(int  i=0; i<v[u].size(); i++)
    {
        int nxt=v[u][i];
        if(nxt==fa[u])
            continue;
        dep[nxt]=dep[u]+1;
        fa[nxt]=u;
        dfs(nxt);
    }
    r[u]=cnt;
}
bool ok(int x,int y)
{
    return l[x]<=l[y]&&r[x]>=l[y];
}
bool check(int u)
{
    for(int i=1; i<=k; i++)
    {
        if(!ok(a[i],u)&&!ok(fa[a[i]],u))
            return false;
    }
    return true;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n>>m;
    for(int i=1; i<=n-1; i++)
    {
        int x,y;
        cin>>x>>y;
        v[x].push_back(y);
        v[y].push_back(x);
    }
    dep[1]=1;
    dfs(1);
    while(m--)
    {
        cin>>k;
        int max_=0,u=0;
        for(int i=1; i<=k; i++)
        {
            cin>>a[i];
            if(dep[a[i]]>max_)
            {
                max_=dep[a[i]];
                u=a[i];
            }
        }
        //cout<<u<<endl;
 
        if(check(u))
            cout<<"YES"<<endl;
        else
            cout<<"NO"<<endl;
    }
    return 0;
}

原文地址:https://www.cnblogs.com/ljxdtc666/p/12584337.html