hdu 6031 Innumerable Ancestors(LCA+二分)

来源:互联网 发布:linux curl 请求url 编辑:程序博客网 时间:2024/05/22 12:46

Innumerable Ancestors

Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 901 Accepted Submission(s): 270

Problem Description
There is a tree having n nodes, labeled from 1 to n. The root of the tree is always 1, and the depth of a node p is the number of nodes on the shortest path between node p and the root.
In computer science, the Lowest Common Ancestor (LCA) of two nodes v and w in a tree is the lowest (i.e. deepest) node that has both v and w as descendants, where we define each node to be a descendant of itself (so if v has a direct connection from w, w is the lowest common ancestor).
You have to answer m queries. Each query gives two non-empty node sets A and B, there might be some nodes in both sets.
You should select one node x from set A, and one node y from set B, x and y can be the same node. Your goal is to maximize the depth of the LCA of x and y.
Please write a program to answer these queries.

Input
The input contains several test cases, no more than 5 test cases.
In each test case, the first line contains two integers n(1≤n≤100000) and m(1≤m≤100000), denoting the number of nodes and queries.
For the next n−1 lines,each line contians two integers a and b, denoting a bi-directional edge between node a and b.
Then there are 2m lines, every two lines describes one query.
For each query, the first line describes the set A.
The first integer k(1≤k≤n) denotes the number of nodes in set A, and the next k integers describing the nodes in set A. There might be some nodes appear multiple times in the set.
The second line describes the set B in the same format of set A.

It is guaranteed that ∑k≤100000 in each test case.

Output
For every query, print a number denoting the answer, which means the maximum depth of the LCA.

Sample Input
7 3
1 2
1 3
3 4
3 5
4 6
4 7
1 6
1 7
2 6 7
1 7
2 5 4
2 3 2

Sample Output
3
4
2
题意:一个n-1条边的树,对于x,y(x∈A,y∈B)求max(deep(lca(x,y)))。
代码:

#include<iostream>#include<stdio.h>#include<stdlib.h>#include<string.h>#include<vector>#include<queue>#include<set>#include<algorithm>#include<map>using namespace std;typedef long long int ll;typedef pair<int,int>pa;const int N=1e5+10;const int MOD=1e9+7;const ll INF=1e18;const int inf=1e4;int read(){    int x=0;    char ch = getchar();    while('0'>ch||ch>'9')ch=getchar();    while('0'<=ch&&ch<='9')    {        x=(x<<3)+(x<<1)+ch-'0';        ch=getchar();    }    return x;}/************************************************************/int head[N<<2];int deep[N];int anc[N][20];int a[N],b[N];int cnt,u,v,ax,bx,n,m;void init(){    cnt=0;    memset(deep,0,sizeof(deep));    memset(head,-1,sizeof(head));    memset(anc,-1,sizeof(anc));}struct node{    int to,next;}edge[N<<2];void add(int fr,int to){    edge[cnt].to=to;    edge[cnt].next=head[fr];    head[fr]=cnt++;}void dfs(int u,int f,int d){    deep[u]=d;    for(int i=head[u];i!=-1;i=edge[i].next)    {        int v=edge[i].to;        if(v==f)continue;        anc[v][0]=u;        dfs(v,u,d+1);    }}void solve(){    for(int j=1;(1<<j)<=n;j++)    {        for(int i=1;i<=n;i++)        {            if(anc[i][j-1]!=-1)            {                anc[i][j]=anc[anc[i][j-1]][j-1];            }        }    }}int lca(int x,int y){    int i,j;    if(deep[x]<deep[y]) swap(x,y);    for(i=0;(1<<i)<=deep[x];i++);    i--;    for(j=i;j>=0;j--)    {        if(deep[x]-(1<<j)>=deep[y])            x=anc[x][j];    }    if(x==y) return x;    for(j=i;j>=0;j--)    {        if(anc[x][j]!=-1&&anc[x][j]!=anc[y][j])        {            x=anc[x][j];            y=anc[y][j];        }    }    return anc[x][0];}int query(int u,int d){    if(d<0) return -1;    if(d==0) return u;    int i;    for(i=0;(1<<i)<=d;i++);    i--;    for(;i>=0;i--)    {        if(d>=(1<<i))        {            d-=(1<<i);            u=anc[u][i];        }    }    return u;}bool check(int x){    set<int>s;    for(int i=1;i<=ax;i++)    {        int dis=deep[a[i]]-x;        int res=query(a[i],dis);        if(res==-1)continue;        s.insert(res);    }    for(int i=1;i<=bx;i++)    {        int dis=deep[b[i]]-x;        int res=query(b[i],dis);        if(s.count(res)) return true;    }    return false;}int main(){    while(~scanf("%d%d",&n,&m))    {        init();        for(int i=1;i<n;i++)        {            scanf("%d%d",&u,&v);            add(u,v);            add(v,u);        }        dfs(1,0,1);        solve();        for(int i=1;i<=m;i++)        {            int l,r,ans;            ans=0;            l=r=1;            scanf("%d",&ax);            for(int j=1;j<=ax;j++)            {                scanf("%d",&a[j]);                r=max(r,deep[a[j]]);            }            scanf("%d",&bx);            for(int j=1;j<=bx;j++)            {                scanf("%d",&b[j]);            }            while(r>=l)            {                int mid=(r+l)>>1;                if(check(mid))                {                    ans=mid;                    l=mid+1;                }                else                    r=mid-1;            }            printf("%d\n",ans);        }    }}
原创粉丝点击