1. 程式人生 > >hdu 6031 Innumerable Ancestors(LCA+剪枝)

hdu 6031 Innumerable Ancestors(LCA+剪枝)

line show view i++ code dfs 過去 rabl using

題目鏈接:hdu 6031 Innumerable Ancestors

題意:

給你一棵n個節點的樹,現在有m個詢問,每次給你兩個點集a,b。

讓你從a,b點集中選兩個點x,y,使得這兩個點的LCA的深度最大。

題解:

標解應該是二分+LCA,不過我試了一下暴力,稍微剪了點枝,就直接過去了。

具體看代碼

技術分享
 1 #include<bits/stdc++.h>
 2 #define F(i,a,b) for(int i=a;i<=b;i++)
 3 using namespace std;
 4 const int N=1e5+7,DEG=20;
 5 int ed,g[N],nxt[2
*N],v[2*N],fa[N][DEG],dep[N]; 6 7 inline void adg(int x,int y){v[++ed]=y,nxt[ed]=g[x],g[x]=ed;} 8 9 void dfs(int u,int pre){ 10 dep[u]=dep[pre]+1,fa[u][0]=pre; 11 F(i,1,DEG-1)fa[u][i]=fa[fa[u][i-1]][i-1]; 12 for(int i=g[u];~i;i=nxt[i])if(v[i]!=pre)dfs(v[i],u); 13 } 14 15 int LCA(int
a,int b){ 16 if(dep[a]>dep[b])a^=b,b^=a,a^=b; 17 if(dep[a]<dep[b])F(i,0,DEG-1)if((dep[b]-dep[a])&(1<<i))b=fa[b][i]; 18 if(a!=b)for(int i=DEG-1;i<0?a=fa[a][0]:0,i>=0;i--) 19 if(fa[a][i]!=fa[b][i])a=fa[a][i],b=fa[b][i]; 20 return a; 21 } 22 23 int n,m,a[N],b[N]; 24
25 bool cmp(const int &a,const int &b) 26 { 27 return dep[a]>dep[b]; 28 } 29 30 int main() 31 { 32 while(~scanf("%d%d",&n,&m)) 33 { 34 memset(g,-1,sizeof(g)); 35 ed=0; 36 F(i,1,n-1) 37 { 38 int x,y; 39 scanf("%d%d",&x,&y); 40 adg(x,y),adg(y,x); 41 } 42 dfs(1,0); 43 F(i,1,m) 44 { 45 int ak,bk; 46 scanf("%d",&ak); 47 F(j,1,ak)scanf("%d",a+j); 48 scanf("%d",&bk); 49 F(j,1,bk)scanf("%d",b+j); 50 sort(a+1,a+1+ak,cmp); 51 sort(b+1,b+1+bk,cmp); 52 int mx=0; 53 F(j,1,ak) 54 { 55 if(dep[a[j]]<=mx)break; 56 F(k,1,bk) 57 { 58 int lca=LCA(a[j],b[k]); 59 mx=max(mx,dep[lca]); 60 } 61 } 62 printf("%d\n",mx); 63 } 64 } 65 return 0; 66 }
View Code

hdu 6031 Innumerable Ancestors(LCA+剪枝)