• hdu6031 Innumerable Ancestors


    hdu6031 Innumerable Ancestors
    倍增
    题意
    给定一张无向图,对于每组询问,给出两个集合 A 与 B
    求 lca(x,y) 最深的时候的深度 x属于A y属于B

    题解
    首先 我们发现答案具有单调性,于是我们就可以二分这个答案 mid
    然后 把 a 集合 的 这个深度的祖先 求出来 然后看 与b 集合的这个深度 祖先 是否有交集就行了
    用set 判断 是否有交集
    用倍增法 快速求出一个点的祖先 求一次 只要 log n

      1 #include <bits/stdc++.h> 
      2 #define ll long long  
      3 #define cl(a,b) memset(a,b,sizeof(a)) 
      4 using namespace std ;  
      5 
      6 const int N = 1e5 + 11 ; 
      7 struct Edge{
      8     int to,pre ; 
      9 }e[N*2] ; 
     10 int n,Q,cnt,k1,k2,ans,l,r ; 
     11 int head[N],deep[N],anc[N][21],a[N],b[N] ;   
     12 
     13 inline int read() 
     14 {
     15     int x = 0 , f = 1 ; 
     16     char ch = getchar() ; 
     17     while(ch<'0'||ch>'9') { if(ch=='-') f = -1 ; ch = getchar() ; } 
     18     while(ch>='0'&&ch<='9') { x = x * 10+ch-48 ; ch = getchar() ; } 
     19     return x * f ; 
     20 }
     21 
     22 inline void add(int x,int y) 
     23 {
     24     e[++cnt].to = y ; 
     25     e[cnt].pre = head[x] ; 
     26     head[x] = cnt ; 
     27 }
     28 
     29 inline void init()  
     30 {
     31     cl( head,-1 ) ;
     32     cl( deep,0 ) ;  
     33     cl( anc,-1 ) ; 
     34     cnt = 0 ; 
     35 }
     36 
     37 inline void dfs(int u,int fa,int d) 
     38 {
     39     deep[ u ] = d ; 
     40     for(int i=head[u]; ~i ; i = e[i].pre)
     41     {
     42         int v = e[ i ].to ; 
     43         if(v==fa) continue ; 
     44         anc[ v ][ 0 ] = u ; 
     45         dfs(v,u,d+1) ; 
     46     }
     47 }
     48 
     49 inline void lca_init() 
     50 {
     51     for(int j=1; (1<<j) <= n ; j++) 
     52         for( int i=1;i<=n;i++ ) 
     53             if(anc[i][j-1]!=-1) 
     54                 anc[i][j] = anc[anc[i][j-1]][j-1] ; 
     55 }
     56 
     57 inline int query(int u,int d) 
     58 //  返回  u的 第 d 个父亲 
     59 {
     60     if( d < 0 ) return -1 ; 
     61     if( d==0 ) return u ; 
     62     int i ; 
     63     for(i=0; (1<<i) <= d ;i++) ;   //  注意 这里有分号相当于 求 log  没有的话 死循环  
     64     i-- ; 
     65     for( ;i>=0;i--)
     66         if(d-(1<<i) >= 0) 
     67         {
     68             d-=(1<<i) ; 
     69             u = anc[u][i] ; 
     70         } 
     71     return u ; 
     72 } 
     73 
     74 inline bool check(int x) 
     75 {
     76     set<int>s ; 
     77     for(int i=1;i<=k1;i++) 
     78     {
     79         int dis = deep[a[ i ]] - x ; 
     80         int ret = query(a[ i ],dis) ; 
     81         if(ret==-1) continue ; 
     82         s.insert(ret) ; 
     83     }
     84     for(int i=1;i<=k2;i++) 
     85     {
     86         int dis = deep[b[ i ]] - x ; 
     87         int ret = query( b[ i ],dis ) ; 
     88         if(s.count(ret)) return true ;   
     89     }
     90     return false ; 
     91 }
     92 
     93 int main() 
     94 { 
     95     while(~scanf("%d%d",&n,&Q)) 
     96     {
     97         init() ; 
     98         int x,y ; 
     99         for(int i=1;i<n;i++) 
    100         {
    101             scanf("%d%d",&x,&y) ; 
    102             add(x,y) ; add(y,x) ; 
    103         }
    104         dfs(1,1,1) ; 
    105         lca_init() ; 
    106         
    107         while(Q--) 
    108         {
    109             scanf("%d",&k1) ; 
    110             l = 1 ; r = 1 ; 
    111             for(int i=1;i<=k1;i++) 
    112                 scanf("%d",&a[ i ]),r = max(r,deep[ a[ i ] ]) ; 
    113             scanf("%d",&k2) ; 
    114             for(int i=1;i<=k2;i++) 
    115                 scanf("%d",&b[ i ]) ;  
    116             while(l<=r) 
    117             {
    118                 int mid = ( l+r ) >>1 ; 
    119                 if(check(mid)) 
    120                 {
    121                     ans = mid ; 
    122                     l = mid + 1 ; 
    123                 }
    124                 else 
    125                     r = mid - 1 ; 
    126             } 
    127             printf("%d
    ",ans ) ; 
    128         }
    129     }
    130     
    131     return 0 ; 
    132 }
  • 相关阅读:
    hdu 2680 最短路径(dijkstra算法+多源最短路径单源化求最小值)
    kmp算法
    STP根交换机,指定端口,根端口,阻塞端口
    python,django安装
    交换机access与trunk口
    树状数组
    hdoj 2191(多重背包)
    hdoj 2601(判断N=i*j+i+j)
    二维背包经典问题
    hdoj 2602(背包)
  • 原文地址:https://www.cnblogs.com/third2333/p/7126846.html
Copyright © 2020-2023  润新知