[CODEVS4605]LCA

来源:互联网 发布:淘宝动漫周边店 编辑:程序博客网 时间:2024/06/18 10:05
题目描述

顾名思义.给一棵有根树,以及一些询问,每次询问树上的2 个节点A、B,求它们的最近公共祖先.


输入描述
第一行一个整数N.接下来N 个数,第i 个数Fi 表示i 的父亲是Fi. 若Fi = 0,则i 为树根.

接下来一个整数M.接下来M 行,每行2 个整数A、B,询问节点(A xor LastAns)、(Bxor LastAns)的最近公共祖先. 其中LastAns 为上一个询问的答案,一开始LastAns = 0.


输出描述

对每一个询问输出相应的答案.


样例输入
10
0 1 2 3 2 4 2 5 4 9
10
3 9
2 7
7 8
1 1
0 6
6 11
6 3
10 7
2 15

7 7


样例输出
3
1
4
5
2
4
2
5
2

5


数据范围及提示

30% n,m≤1000

100% n,m≤100,000



题解:LCA裸题


倍增版:

#include<iostream>#include<cstring>#include<cstdlib>#include<cstdio>#include<cmath>#include<algorithm>using namespace std;const int N=100010;const int LOG=20;int n, m, root;void Getin( int &shu ) {char c; int f=1; shu=0;for( c=getchar(); c<'0' || c>'9'; c=getchar() ) if( c=='-' ) f=-1;for( ; c>='0' && c<='9'; c=getchar() ) shu=shu*10+c-'0';shu*=f;}int fir[N], ecnt;struct node{ int e, next; }edge[N<<1];void Link( int s, int e ) {edge[++ecnt].e=e; edge[ecnt].next=fir[s]; fir[s]=ecnt;edge[++ecnt].e=s; edge[ecnt].next=fir[e]; fir[e]=ecnt;}int fa[N][LOG+5], dep[N];void DFS( int r, int f, int d ) {dep[r]=d;for( int i=fir[r]; i; i=edge[i].next )if( edge[i].e!=f ) {fa[edge[i].e][0]=r;DFS( edge[i].e, r, d+1 );}}void Build() {DFS( root, 0, 1 );for( int j=1; j<=LOG; j++ )for( int i=1; i<=n; i++ )fa[i][j]=fa[ fa[i][j-1] ][j-1];}int getk( int r ,int k ) {for( int i=0; i<=LOG; i++ )if( k&( 1<<i ) ) r=fa[r][i];return r;}int getd( int r, int d ) {return getk( r, dep[r]-d );}int p1, p2;int LCA_Find() {    if( dep[p1]<dep[p2] ) swap( p1, p2 );     p1=getd( p1, dep[p2] );if( p1==p2 ) return p1;for( int i=LOG; i>=0; i-- )if( fa[p1][i]!=fa[p2][i] )p1=fa[p1][i], p2=fa[p2][i];return fa[p1][0];}int main() {Getin(n); for( int i=1; i<=n; i++ ) {int f; Getin( f );if( !f ) { root=i; continue; }Link( f, i );}Build();Getin(m);int w=0;for( int i=1; i<=m; i++ ) {Getin( p1 ); Getin( p2 );p1^=w; p2^=w;w=LCA_Find();printf( "%d\n", w );}return 0;}



链剖版:

#include<iostream>#include<cstring>#include<cstdlib>#include<cstdio>#include<cmath>#include<algorithm>using namespace std;const int N=100010;int n, m, root;void Getin( int &shu ) {char c; int f=1; shu=0;for( c=getchar(); c<'0' || c>'9'; c=getchar() ) if( c=='-' ) f=-1;for( ; c>='0' && c<='9'; c=getchar() ) shu=shu*10+c-'0';shu*=f;}int fir[N], ecnt;struct node{ int e, next; }edge[N];void Link( int s, int e ) {edge[++ecnt].e=e; edge[ecnt].next=fir[s]; fir[s]=ecnt;}int fa[N], dep[N], siz[N], son[N];void DFS1( int r, int d ) {dep[r]=d; siz[r]=1;for( int i=fir[r]; i; i=edge[i].next ) {DFS1( edge[i].e, d+1 );siz[r]+=siz[ edge[i].e ];if( siz[ edge[i].e ]>siz[ son[r] ] ) son[r]=edge[i].e;}}int top[N];void DFS2( int r ) {if( son[r] ) top[ son[r] ]=top[r], DFS2( son[r] );for( int i=fir[r]; i; i=edge[i].next )if( edge[i].e!=son[r] ) {top[ edge[i].e ]=edge[i].e;DFS2( edge[i].e );}}int p1, p2;int LCA() {while( top[p1]!=top[p2] ) {if( dep[ top[p1] ]>dep[ top[p2] ] ) p1=fa[ top[p1] ];else p2=fa[ top[p2] ];}return dep[p1]<dep[p2] ? p1 : p2;}int main() {Getin(n); for( int i=1; i<=n; i++ ) {Getin( fa[i] );if( !fa[i] ) { root=i; continue; }Link( fa[i], i );}DFS1( root, 1 );top[root]=1; DFS2(root);Getin(m);int w=0;for( int i=1; i<=m; i++ ) {Getin( p1 ); Getin( p2 );p1^=w; p2^=w;w=LCA();printf( "%d\n", w );}return 0;}