题目描述
顾名思义.给一棵有根树,以及一些询问,每次询问树上的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; }