天天看點

HDU 5927 Auxiliary Set

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. 

Input

T≤1000

T≤1000), which indicates the number of test cases. 

For each test case, the first line contains two integers n (

1≤n≤100000

1≤n≤100000), q (

0≤q≤100000

0≤q≤100000). 

In the following n -1 lines, the i-th line contains two integers 

ui,vi(1≤ui,vi≤n)

ui,vi(1≤ui,vi≤n)indicating there is an edge between 

ui

uii and 

vi

vi in the tree. 

In the next q lines, the i-th line first comes with an integer 

mi(1≤mi≤100000)

mi(1≤mi≤100000)indicating the number of vertices in the query set.Then comes with mi different integers, indicating the nodes in the query set. 

It is guaranteed that 

∑qi=1mi≤100000

∑i=1qmi≤100000. 

It is also guaranteed that the number of test cases in which 

n≥1000

n≥1000  or 

∑qi=1mi≥1000

∑i=1qmi≥1000 is no more than 10. 

Output

For each test case, first output one line "Case #x:", where x is the case number (starting from 1). 

Then q lines follow, i-th line contains an integer indicating the size of the auxiliary set for each query. 

Sample Input

1
6 3
6 4
2 5
5 4
1 5
5 3
3 1 2 3
1 5
3 3 1 4      

Sample Output

Case #1:
3
6
3      
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 2e5 + 10;
const int INF = 0x7FFFFFFF;
const int mod = 1e9 + 7;
const int low(int x) { return x&-x; }
int T, n, m, x, y;
int ft[N],nt[N],u[N],sz;
int L[N], R[N], t;
int f[N],dep[N],a[N],b[N], fa[N], cnt[N];

int sum(int x) {
  int res = 0;
  for (int i = x;i;i-=low(i)) {
    res+=f[i];
  }
  return res;
}

void add(int x,int y) {
  for (int i = x;i<=n;i+=low(i)) f[i]+=y;
}

void dfs(int x,int y){
  dep[x] = dep[y] + 1;
  fa[x] = y;
  L[x] = ++t;
  cnt[x] = 0;
  add(L[x], 1);
  for (int i = ft[x];~i;i=nt[i]) {
    if (u[i] == y) continue;
    dfs(u[i], x);
    cnt[x]++;
  }
  R[x] = t;
}

bool cmp(int x,int y) {
  return dep[x]>dep[y];
}

int main(){
  int cas = 1;
  for (scanf("%d",&T);T--;cas++) {
    scanf("%d%d",&n, &m);
    sz = t = f[n] = dep[0] = 0;
    for (int i = 1;i <= n;i++) ft[i] = -1;
    for (int i = 1;i < n;i++) {
      scanf("%d%d",&x,&y);
      f[i] = 0;
      u[sz] = y; nt[sz] = ft[x]; ft[x] = sz++;
      u[sz] = x; nt[sz] = ft[y]; ft[y] = sz++;
    }
    dfs(1,0);
    printf("Case #%d:\n",cas);
    while (m--) {
      scanf("%d",&x);
      for (int i = 0;i<x;i++) {
        scanf("%d",&a[i]);
      }
      sort(a,a+x,cmp);
      int ans = n - x;
      for (int i = 0;i<x;i++) {
        add(L[a[i]],-1);
        if (cnt[a[i]] > 1) ans++;
        b[i] = 0;
        if (sum(R[a[i]]) - sum(L[a[i]] - 1) == 0) {
          cnt[fa[a[i]]]--; b[i] = 1;
        }
      }
      printf("%d\n",ans);
      for (int i = 0;i<x;i++) {
        add(L[a[i]],1);
        if (b[i]) {
          cnt[fa[a[i]]]++;
        }
      }
    }
  }
  return 0;
}