hdu5927 dfs

给你一个树和几个不重要的点,求重要的点和是至少两个重要点的最近公共祖先的点的个数。
先预处理出每个点的儿子个数,和每个节点的父节点。
每次询问把不重要点的构图(只需要遍历每个不重要点的子代,找到是否有要重要即可),如果不重要点是两个以上的重要点的最近公共祖先,那么就答案+1,最后加上重要点的个数,即为答案。

#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int N=100005;
int n,m,head[N],num[N],pre[N],a[N],e[N*2][2],cnt;
vector<int> q[N];
void add(int u,int v)
{
    e[++cnt][0]=u;
    e[cnt][1]=head[v];
    head[v]=cnt;
    e[++cnt][0]=v;
    e[cnt][1]=head[u];
    head[u]=cnt;
}
void dfs(int u,int fa)
{
    for(int i=head[u]; ~i; i=e[i][1])
        if(e[i][0]!=fa)
            num[u]++,pre[e[i][0]]=u,dfs(e[i][0],u);
}
int dd(int x)
{
    int aa=0,cn=q[x].size();
    for(int i=0;i<cn;i++)
        if(dd(q[x][i])>=1)
            aa++;
    return num[x]-cn+aa;
}
int main()
{
    int T,u,v;
    scanf("%d",&T);
    for(int cas=1;cas<=T;cas++)
    {
        printf("Case #%d:\n",cas);
        cnt=0;
        memset(head,-1,sizeof(head));
        scanf("%d%d",&n,&m);
        for(int i=1; i<n; i++)
            scanf("%d%d",&u,&v),add(u,v);
        dfs(1,0);
        while(m--)
        {
            int t,ans;
            scanf("%d",&t);
            ans=n-t;
            for(int i=0; i<t; i++)
                scanf("%d",&a[i]),q[a[i]].clear();
            for(int i=0;i<t;i++)
                q[pre[a[i]]].push_back(a[i]);
            for(int i=0; i<t; i++)
               ans+=(dd(a[i])>=2);
            printf("%d\n",ans);
        }
        memset(num,0,sizeof(num));
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值