HDU6031 Innumerable Ancestors

O(n^2)暴力枚举点然后算LCA显然是不可行的。

看到这个数据范围,考虑二分。我们二分枚举LCA的深度mid,然后把set A中每个点深度为mid的祖宗找出来,看set B中每个点深度为mid的祖宗有没有与set A刚才找到的祖宗重合,如果有重合,l=mid+1,否则r=mid-1。

记得多组数据。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cmath>
using namespace std;
#define int long long
const int N=1e5,LOGN=20;
int fa[N+10][20],head[N+10],ver[N*2+10],nxt[N*2+10],tot=0,dep[N+10];
void add(int x,int y)
{
    ver[++tot]=y;
    nxt[tot]=head[x];
    head[x]=tot;
}
int getfa(int x,int k)
{
    int ans=x,pos=0;
    while((1<<pos)<=k)
    {
        if((1<<pos)&k) ans=fa[ans][pos];
        pos++;
    }
    return ans;
}
bool vis[N+10];
int que[N+10],h=1,t=0,zzt;
void bfs()
{
    que[++t]=1;
    dep[1]=1;
    while(h<=t)
    {
        int x=que[h]; h++;
        // printf("x:%lld\n",x);
        vis[x]=1;
        for(int i=head[x];i;i=nxt[i])
        {
            int y=ver[i];
            if(vis[y]) continue;
            fa[y][0]=x;
            dep[y]=dep[x]+1;
            // maxdep=max(maxdep,dep[y]);
            for(int j=1;j<=zzt;j++) fa[y][j]=fa[fa[y][j-1]][j-1];
            que[++t]=y;
        }
    }
}
vector<int> s1,s2;
int k1,k2;
int book[N+10];
int maxdep; 
int bs(int pos) //binary search
{
    int l=1,r=maxdep,ans=0;
    while(l<=r)
    {
        int mid=(l+r)/2;
        // printf("mid:%lld\n",mid);

        bool flag=0;

        for(int i=0;i<k1;i++) 
            if(dep[s1[i]]>=mid)
                book[getfa(s1[i],dep[s1[i]]-mid)]=pos;
        for(int i=0;i<k2;i++)
            if(dep[s2[i]]>=mid)
                if(book[getfa(s2[i],dep[s2[i]]-mid)]==pos)
                {
                    flag=1;
                    break;
                }
        if(flag)
        {
            l=mid+1;
            ans=mid;
        }
        else r=mid-1;
    }
    return ans;
}
signed main()
{
    int n,m;
    while(~scanf("%lld %lld",&n,&m))
    {
        memset(book,0,sizeof(book));
        h=1;t=0;
        memset(vis,0,sizeof(vis));memset(head,0,sizeof(head));tot=0;
        
        zzt=log2(n)+1;
        for(int i=1;i<n;i++)
        {
            int u,v;
            scanf("%lld %lld",&u,&v);
            add(u,v);
            add(v,u);
        }
        bfs();
        for(int i=1;i<=m;i++)
        {
            maxdep=0;
            s1.clear();s2.clear();
            scanf("%lld",&k1);
            for(int j=1;j<=k1;j++)
            {
                int x;
                scanf("%lld",&x);
                s1.push_back(x);
                maxdep=max(maxdep,dep[x]);
            }
            scanf("%lld",&k2);
            for(int j=1;j<=k2;j++)
            {
                int x;
                scanf("%lld",&x);
                s2.push_back(x);
                maxdep=max(maxdep,dep[x]);
            }
            printf("%lld\n",bs(i));
        }
    }
    return 0;
}
posted @ 2020-10-28 17:39  zzt1208  阅读(61)  评论(0编辑  收藏  举报