zoukankan      html  css  js  c++  java
  • 【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
    ",R);
     99             else
    100               printf("%d
    ",L);
    101         }
    102     }
    103 return 0;
    104 }
    View Code
  • 相关阅读:
    OpenMP笔记(一)
    Ubuntu16.04编译OpenCV3.4.7
    Ubuntu16.04编译tensorflow的C++接口
    win10编译tensorflow C++接口
    Qt5学习笔记(1)-环境配置(win+64bit+VS2013)
    Qt creator中配置opencv win7 64bit
    MYSQL其他常用函数
    MySQL 8.0中的新增功能
    MySQL中的JSON函数(三)修改JSON的函数
    MySQL中的JSON函数(二)查询JSON函数
  • 原文地址:https://www.cnblogs.com/LQLlulu/p/8955220.html
Copyright © 2011-2022 走看看