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 倍增 - 题意详细概括 - 算法详解