CodeForces1328E dfs,树的深度

题意

给出一个有n个顶点的有根树,顶点的编号从1到n。树的根节点编号恒为1。
一棵数是具有n-1条边的联通图。
给出 m 个询问。第i个询问由 k_i 个不同的节点 v_i[1], v_i[2], …, v_i[k_i]组成. 你的任务是判断是否存在一条从根节点到u的路径,使得给出的k_i个节点要么在这条路径上,要么与该路径上的某个节点距离为1。

题解

  • 针对单个询问,分析可得题目要求路径上所有节点的本身/儿子节点组成的集合必须包含给出的所有节点,聚焦结点的深度,容易意识到只需要check给出的节点中最深的节点到根节点的链就可以了。
  • 题目没有强制在线,所以可以考虑离线之后用一次dfs动态维护当前节点与根节点的链上所有节点及其儿子的集合,然后对每个节点到跟的链直接判断query
    时间复杂度O(N) + O(ΣK)

代码

#include<bits/stdc++.h>
using namespace std;
#define PII pair<int,int>
#define fi first
#define se second
#define mp make_pair
#define LL long long
const int maxn = 2e5 + 10;
const int mod = 1e9 + 7; 
int N,M,S;
struct Edge{
    int to,next;
}edge[maxn * 2];
int head[maxn],tot;
void init() {
    for(int i = 0; i <= N ; i ++) head[i] = -1;
    tot = 0;
}
void add(int u,int v) {
    edge[tot].to = v;
    edge[tot].next = head[u];
    head[u] = tot++;
}
int deep[maxn];
void dfs_deep(int u,int fa) {
    for(int i = head[u]; ~i; i = edge[i].next) {
        int v = edge[i].to;
        if(v == fa) continue;
        deep[v] = deep[u] + 1;
        dfs_deep(v,u);
    }
}
vector<vector<int> >Q[maxn];
bool flag[maxn];
bool ans[maxn];
void dfs(int u, int fa) {
    for(int i = head[u]; ~i ; i = edge[i].next) {
        int v = edge[i].to;
        if(v == fa) continue;
        flag[v] = true;
    }
    for(int i = 0; i < Q[u].size(); i ++) {
        ans[Q[u][i][0]] = true;
        for(int j = 1; j < Q[u][i].size(); j ++) {
            if(!flag[Q[u][i][j]]) {
                ans[Q[u][i][0]] = false;
                break;
            }
        }    
    }
    for(int i = head[u]; ~i; i = edge[i].next) {
        int v = edge[i].to;
        if(v == fa) continue;
        dfs(v,u);
    }
    for(int i = head[u]; ~i; i = edge[i].next) {
        int v = edge[i].to;
        if(v == fa) continue;
        flag[v] = false;
    }
}
int main(){
    scanf("%d%d",&N,&M); init();
    for(int i = 1; i <= N - 1; i ++) {
        int u,v; scanf("%d%d",&u,&v);
        add(u,v); add(v,u);
    }
    deep[1] = 1;
    dfs_deep(1,-1);
    for(int i = 1; i <= M; i ++) {
        vector<int>P;
        P.push_back(i);
        int k; scanf("%d",&k);
        int t = 1;
        for(int i = 1; i <= k ; i ++) {
            int a; scanf("%d", &a);
            if(deep[a] > deep[t]) {
                t = a;
            }
            P.push_back(a);
        }
        Q[t].push_back(P);
    }
    flag[1] = 1;
    dfs(1,-1);
    for(int i = 1; i <= M ; i ++) {
        if(ans[i]) puts("YES");
        else puts("NO");
    }
    return 0;
}


posted @ 2020-10-03 15:42  Hugh_Locke  阅读(185)  评论(0编辑  收藏  举报