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
The first line contains only one integer T (T≤1000T≤1000), which indicates the number of test cases.
For each test case, the first line contains two integers n (1≤n≤1000001≤n≤100000), q (0≤q≤1000000≤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 uiuii and vivi 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≥1000n≥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
Hint
For the query {1,2, 3}: •node 4, 5, 6 are important nodes For the query {5}: •node 1,2, 3, 4, 6 are important nodes •node 5 is the lea of node 4 and node 3 For the query {3, 1,4}: • node 2, 5, 6 are important nodes
题意:给定一棵树,1为根节点,给定q个操作,每个操作都是把一个集合中的节点变成不重要节点,节点外的都为重要节点,但是如果集合内的某个点是集合外某两个点的最近公共祖先,那么这个集合内的点也是重要节点,要你输出对于每次操作,有多少个重要节点
题解:这题一直在想着用LCA搞,然后又怕T,听队友说按照深度搞,最后队友做出来了(Tql.......),就是从1节点开始跑一边dfs求出每个点的深度,记录每个节点的父节点,直系子节点个数,对于当前集合内的点,我按照深度从大到小排序,深度大的在下面,先看深度大的子节点,如果子节点个数大于等于2个,那么就说明这个点也可以变成重要节点,则ans++;如果只有一个子节点就不做处理,没有子节点就把这个节点删掉(其实就是让父节点的子节点个数减1)这时候父节点可能由原来的2个子节点变成了1个子节点了,这时候是刚好不满足重要节点的,很多人会想如果他有两个子节点,ans++,不对他删除,他的父节点怎么办,实际上就是如果他的父节点也有两个子节点,其中一个就包括它,但是它还有两个子节点,那么它的子节点跟它的兄弟节点的LCA就是它的父亲,这时候也满足它的父节点个数等于2,ans++;实在不太理解画图解释吧!
第一种情况:
第二种情况:
第三种情况:
总结:这些情况还是集合中节点比较密集在一块的情况,其实在数据上,好多节点不是在一堆,那么影响集合中的点的就是集合点的子节点了,语文水平有限,实在看不懂的就看代码吧,很容易理解的,有问题欢迎指正~
代码:
#include<bits/stdc++.h>
#define N 100005
using namespace std;
int t,n,m,q,index=0,ans;
int a[N],fa[N],son[N],sons[N],deg[N];
vector<int>v[N];
void dfs(int x,int pre)
{
deg[x]=deg[pre]+1;
for(int i=0;i<v[x].size();i++)
{
int nex=v[x][i];
if(!deg[nex])
{
fa[nex]=x;
dfs(nex,x);
son[x]++;
}
}
return ;
}
bool cmp(int i,int j)
{
return deg[i]>deg[j];
}
int main()
{
scanf("%d",&t);
while(t--)
{
memset(deg,0,sizeof(deg));
memset(son,0,sizeof(son));
memset(fa,0,sizeof(fa));
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)v[i].clear();
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
v[x].push_back(y);
v[y].push_back(x);
}
dfs(1,0);
printf("Case #%d:\n",++index);
while(q--)
{
scanf("%d",&m);
ans=n-m;
for(int i=1;i<=m;i++)scanf("%d",&a[i]);
sort(a+1,a+m+1,cmp);
// for(int i=1;i<=m;i++)cout<<son[a[i]]<<" ";cout<<endl;
for(int i=1;i<=m;i++)sons[a[i]]=son[a[i]];
for(int i=1;i<=m;i++)
{
if(sons[a[i]]>=2)ans++;
else if(sons[a[i]]==0)sons[fa[a[i]]]--;
}
printf("%d\n",ans);
}
}
}