3055: Nearest Common Ancestors
Time Limit: 1 Sec Memory Limit: 128 MBDescription
给定N个节点的一棵树,有K次查询,每次查询a和b的最近公共祖先。
样例中的16和7的公共祖先(LCA:Least Common Ancestors)是4。
Input
第一行两个整数N(1 < N <= 105)、K(1 <= K <= 105)
第2~N行,每行两个整数a、b(1 <= a,b <= N),表示a是b的父亲。
第N+1~N+K+1行,每行两个整数a、b(1 <= a,b <= N),表示询问a和b的最近公共祖先是谁。
Output
输出K行,第i行表示第i个查询的最近公共祖先是谁。
Sample Input
16 11 148 510 165 94 68 44 101 136 1510 116 710 216 38 116 1216 7
Sample Output
4
HINT
30%数据 N<=20,K<=5。小数据,方便调试
50%数据 N<=1000,K<=1000。中数据,暴力可过
100%数据 1 < N <= 105,1 <= K <= 105。大数据,请使用树上倍增、LCA转RMQ&ST、离线Tarjan、树链剖分求LCA
Source
poj1330改
- #include<stdio.h>
- int n,t;
- int f[100001][21];
- /*‘f[i][j]从第i个点向上蹦2^j步的落脚点’*/
- int log_me[100001];
- int head[100001];
- int to[100001];
- int next[100001];
- int level[100001];
- int queue[100001];
- int power[21];
- int idx,all_fa,max_dep;
- bool is[100001];
- void bfs(int p)
- {
- int front,tail;
- front=tail=0;
- queue[tail++]=p;
- while(front<tail)
- {
- int idx2=queue[front++];
- for(int i=head[idx2];i;i=next[i])
- {
- level[to[i]]=level[idx2]+1;
- queue[tail++]=to[i];
- if(level[to[i]]>max_dep)
- max_dep=level[to[i]];
- }
- }
- }
- int main()
- {
- scanf("%d%d",&n,&t);
- for(int i=1;i<n;i++)
- {
- int a,b;
- scanf("%d%d",&a,&b);
- f[b][0]=a;
- next[++idx]=head[a];
- head[a]=idx;
- to[idx]=b;
- is[b]=true;
- }
- log_me[0]=-1;
- for(int i=1;i<=n;i++)
- {
- log_me[i]=log_me[i>>1]+1;
- if(!is[i])
- all_fa=i;
- }
- power[0]=1;
- for(int i=1;i<=17;i++)
- power[i]=power[i-1]*2;
- bfs(all_fa);
- f[all_fa][0]=all_fa;
- f[0][0]=all_fa;
- for(int j=1;j<=17;j++)
- for(int i=0;i<=n;i++)
- f[i][j]=f[f[i][j-1]][j-1];
- for(;t;t--)
- {
- int a,b;
- scanf("%d%d",&a,&b);
- if(a==b)
- {
- printf("%d\n",a);
- continue;
- }
- int deep,low,diff_val;
- if(level[a]>level[b])
- deep=a,low=b;
- else
- deep=b,low=a;
- diff_val=level[deep]-level[low];
- for(;level[deep]>level[low];diff_val=level[deep]-level[low])
- deep=f[deep][log_me[diff_val]];
- if(deep==low)
- {
- printf("%d\n",deep);
- continue;
- }
- int dep=log_me[level[deep]];
- while(dep>=0)
- {
- if(f[deep][dep]!=f[low][dep])
- {
- deep=f[deep][dep];
- low=f[low][dep];
- dep=log_me[level[deep]];
- }
- dep--;
- }
- printf("%d\n",f[deep][0]);
- }
- }