^ HDU 6031] ^ Innumerable Ancestors

meaning of the title

  There is a tree with n nodes, there are m queries, each query gives two non-empty node sets A and B, and some nodes may be in both sets at the same time. You need to choose a node x and y from A and B respectively (can be the same node) Your goal is to maximize the depth of LCA(x,y). n,m<=100000

analyze

  The complexity of each query of the LCA algorithm is logn. If each query enumerates two sets, then the amortized time complexity is n^2logn (like...about... right??

  I heard that this question can be burst by sorting two sets? ? ? ? Why did I fail? Is the posture wrong?

  The standard solution to this problem is bisection + LCA (multiplication preprocessing)

  For each query, we dichotomize the maximum depth. Then how to write check? Add the point in the set A, whose depth is the value of this dichotomy, into a set. Then enumerate set B, if the ancestor of this depth in B is in this set, then return correct.

  

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <iostream>
  5 #include <vector>
  6 #include <queue>
  7 #include <set>
  8 
  9 using namespace std;
 10 const int maxn=100000+100;
 11 vector<int>G[maxn];
 12 int n,m,k1,k2;
 13 int f[maxn][20],d[maxn],A[maxn],B[maxn];
 14 void bfs(){
 15     queue<int>q;
 16     memset(d,0,sizeof(d));
 17     memset(f,0,sizeof(f));
 18     q.push(1);d[1]=1;
 19     while(!q.empty()){
 20         int u=q.front();q.pop();
 21         for(int i=0;i<G[u].size();i++){
 22             int v=G[u][i];
 23             if(d[v])continue;
 24             d[v]=d[u]+1;
 25             f[v][0]=u;
 26             for(int j=1;j<=19;j++){
 27                 f[v][j]=f[f[v][j-1]][j-1];
 28             }
 29             q.push(v);
 30         }
 31     }
 32     return ;
 33 }
 34 int lca(int x,int y){
 35     if(d[x]>d[y])swap(x,y);
 36     for(int i=19;i>=0;i--)
 37         if(d[f[y][i]]>=d[x])y=f[y][i];
 38     if(x==y)return x;
 39     for(int i=19;i>=0;i--)
 40         if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
 41     return f[x][0];
 42 }
 43 int query(int u,int fa){
 44     if(fa==0)return u;
 45     for(int i=20;i>=0;i--){
 46         if(fa>=(1<<i)){
 47             u=f[u][i];
 48             fa-=(1<<i);
 49         }
 50     }
 51     return u;
 52 }
 53 bool check(int deep){
 54     set<int>S;
 55     for(int i=1;i<=k1;i++){
 56         if(deep>d[A[i]])continue;
 57         int res=query(A[i],d[A[i]]-deep);
 58         S.insert(res);
 59     }
 60     for(int i=1;i<=k2;i++){
 61         if(deep>d[B[i]])continue;
 62         int res=query(B[i],d[B[i]]-deep);
 63         if(S.count(res))return true;
 64     }
 65     return false;
 66 }
 67 int main(){
 68     while(scanf("%d%d",&n,&m)!=EOF){
 69         for(int i=1;i<=n;i++)G[i].clear();
 70         for(int i=1;i<n;i++){
 71             int a,b;
 72             scanf("%d%d",&a,&b);
 73             G[a].push_back(b);
 74             G[b].push_back(a);
 75         }
 76         bfs();
 77         for(int i=1;i<=m;i++){
 78             int L,R,mid;
 79             scanf("%d",&k1);
 80             R=1;
 81             for(int j=1;j<=k1;j++){
 82                 scanf("%d",&A[j]);
 83                 R=max(R,d[A[j]]);
 84             }
 85             scanf("%d",&k2);
 86             for(int j=1;j<=k2;j++)
 87                 scanf("%d",&B[j]);
 88             L=1;
 89             while(L+1<R){
 90                 mid=L+(R-L)/2;
 91                 if(check(mid)){
 92                     L=mid;
 93                 }else{
 94                     R=mid-1;
 95                 }
 96             }
 97             if(check(R))
 98               printf("%d\n",R);
 99             else
100               printf("%d\n",L);
101         }
102     }
103 return 0;
104 }
View Code

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324897546&siteId=291194637