点击打开链接
看了题解才会... 之前还一直想用LCA怎么搞...
对于一个非重要点 只要其下至少两颗子树上分别有两个重要点 那这个非重要点一定是他们的LCA 也变成了重要节点
dfs一遍 记录每个节点的直接孩子有几个 记为son[cur] 对于每一个查询 把点按深度从深到浅排序 然后扫一遍
如果当前点的son[cur]==0 那么以当前点为根的子树上已经不存在重要点 其父节点也就少了一个提供重要点的来源 son[fa[cur]]--
如果当前点的son[cur]==1 对自己对父节点都没啥影响 忽略
如果当前点的son[cur]==2 那么他也会被记为重要点
using namespace std;
struct node1
{
    int v;
    int next;
};
node1 edge[200010];
int first[100010],fa[100010],son[100010],deep[100010];
int n,num;
bool cmp(int u,int v)
{
    return deep[u]>deep[v];
}
void addedge(int u,int v)
{
    edge[num].v=v;
    edge[num].next=first[u];
    first[u]=num++;
    return;
}
void dfs(int cur,int dep)
{
    int i,v;
    son[cur]=0,deep[cur]=dep;
    for(i=first[cur];i!=-1;i=edge[i].next)
    {
        v=edge[i].v;
        if(v!=fa[cur])
        {
            fa[v]=cur,son[cur]++;
            dfs(v,dep+1);
        }
    }
    return;
}
int main()
{
    int tem[100010],pre[100010];
    int t,cas,q,k,i,u,v,ans;
    scanf("%d",&t);
    for(cas=1;cas<=t;cas++)
    {
        scanf("%d%d",&n,&q);
        memset(first,-1,sizeof(first));
        num=0;
        for(i=1;i<=n-1;i++)
        {
            scanf("%d%d",&u,&v);
            addedge(u,v);
            addedge(v,u);
        }
        fa[1]=-1;
        dfs(1,1);
        printf("Case #%d:\n",cas);
        while(q--)
        {
            scanf("%d",&k);
            for(i=1;i<=k;i++)
            {
                scanf("%d",&pre[i]);
                tem[pre[i]]=son[pre[i]];
            }
            sort(pre+1,pre+k+1,cmp);
            ans=n-k;
            for(i=1;i<=k;i++)
            {
                if(tem[pre[i]]>=2) ans++;
                else if(tem[pre[i]]==0) tem[fa[pre[i]]]--;
            }
            printf("%d\n",ans);
        }
    }
    return 0;
} 如果当前点的son[cur]==1
                










