HDU 6031] Innumerable Ancestors

Posted 蒟蒻LQL

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 6031] Innumerable Ancestors相关的知识,希望对你有一定的参考价值。

题意

  有一棵有n个结点的树,这里有m个询问,每个询问给出两个非空的结点集合A和B,有些结点可能同时在这两个集合当中。你需要从A和B中分别选择一个节点x和y(可以是同一个结点)你的目标是使LCA(x,y)的深度最大。n,m<=100000

分析

  LCA算法每次查询的复杂度都是logn的,如果每个查询都枚举两个集合,那么均摊的时间复杂度是n^2logn(好像··大概··是吧??

  听说这个题可以通过给两个集合排序爆过去????为啥我失败了?姿势不对吗?

  这个题的标准解法是二分+LCA(倍增预处理)

  对于每次查询,我们二分最大深度。然后怎么写check呢?把集合A里面的,深度为这个二分出来的值的这个点,加入一个set。然后枚举集合B,如果B里面这个深度的祖先在这个set里面,那么就返回正确。

  

技术分享图片
  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

 

以上是关于HDU 6031] Innumerable Ancestors的主要内容,如果未能解决你的问题,请参考以下文章

HDU 6031 Innumerable Ancestors

HDU 6031] Innumerable Ancestors

HDU6031 Innumerable Ancestors 倍增 - 题意详细概括 - 算法详解

HDU5036 Explosion(期望 bitset)

洛谷P3379lca,HDU2586,洛谷P1967货车运输,倍增lca,树上倍增

hdu 3549 Flow Problem