dfs序 树状数组--hdu5927 Auxiliary Set

来源:互联网 发布:平价化妆水知乎 编辑:程序博客网 时间:2024/06/11 16:24
Given a rooted tree with n vertices, some of the vertices are important. 

An auxiliary set is a set containing vertices satisfying at least one of the two conditions: 

It is an important vertex 
It is the least common ancestor of two different important vertices. 

You are given a tree with n vertices (1 is the root) and q queries. 

Each query is a set of nodes which indicates the unimportant vertices in the tree. Answer the size (i.e. number of vertices) of the auxiliary set for each query. 

//dfs序将子树的问题转换为序列上的问题

//再配合上数据结构,ST表、线段树、树状数组etc

//然后如果一个坏点有两个子儿子的子树内存在好点则这个点就是好点 <- LCA

#include <iostream>

#include <cstdio>

#include <vector>

#include <cstring>

using namespacestd;

const int maxn =1e5 + 5;

vector<int> mp[maxn];

int in[maxn],out[maxn];//dfs

int te = 0;

int assist[maxn];

int n;

int unimp[maxn];

int fat[maxn] = {0,0};


void init(int n)

{

    te = 0;

    for (int i =1; i <= n; i ++) {

        mp[i].clear();

    }

}

void dfs(int s)

{

    in[s] = ++te;

    for(int i =0;i < mp[s].size();i ++)

    {

        if(mp[s][i] !=fat[s]){

            fat[mp[s][i]] = s;

            dfs(mp[s][i]);

        }

    }

    out[s] =te;

}

void add(int x,int d)

{

    for (; x <=n; x += (x & -x)) {

        assist[x] += d;

    }

}

int query(int x)

{

    int res =0;

    for(;x >0 ;x -= (x & -x)){

        res += assist[x];

    }

    return res;

}

bool check(int x)

{

    int cnt =0;

    for (int i =0; i < mp[x].size(); i ++) {

        int y =mp[x][i];

        if(y !=fat[x]){

            if(query(out[y]) -query(in[y] -1) != out[y] -in[y] + 1)

                if(++cnt ==2) returntrue;

        }

    }

    returnfalse;

}

int main()

{

    int T;cin >> T;

    int q,u,v;

    for (int cn =1; cn <= T; cn ++) {

        scanf("%d%d",&n,&q);

        init(n);

        for (int i =0; i < n -1; i ++) {

            scanf("%d%d",&u,&v);

            mp[u].push_back(v);

            mp[v].push_back(u);

        }

        dfs(1);

      

        printf("Case #%d:\n",cn);

        int sz =0;

        for (int i =0; i < q; i ++) {

            scanf("%d",&sz);

            for (int j =0; j < sz; j ++) {

                scanf("%d",&unimp[j]);

                add(in[unimp[j]],1);

            }

            int ans =n;

            for (int j =0; j < sz; j ++) {

                if(!check(unimp[j])) ans--;//if  unimp[j] has two import son return true

            }

            for (int j =0; j < sz; j ++) {

                add(in[unimp[j]], -1);

            }

            printf("%d\n",ans);

        }

       

    }

    return0;

}



原创粉丝点击