hdu6031 Innumerable Ancestors

Posted third2333

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\n",ans ) ; 
128         }
129     }
130     
131     return 0 ; 
132 }

 

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

HDU 6031 Innumerable Ancestors

HDU 6031] Innumerable Ancestors

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

HDU - 1535 Invitation Cards 前向星SPFA

hdu 3549 Flow Problem

LOJ #6031 字符串