题目描述Bessie和Jon每天都要去他们所居住的小镇的某些地方游玩。有趣的是,他们居住的小镇是一个树的结构,也就意味是,小镇的每个地方之间有且仅有一条通路(不是指一条边,而是指一条通路),每个地方都会有且仅有一个父亲地点(除了小镇的城镇中心,它没有祖先)。小镇共有N个地点(1 <= N <= 1,000),编号1~N。点1是镇的中心。Bessie和Jon决定每天都要在游玩后见面,他们见面的地点总是在他们游玩的两个地方之间的那条通路中,离城镇中心最近的地方,下面给出他们的旅行日程,你需要帮他们每天的见面地点。你可以理解为城镇中心就是成为在这个树结构上的根。地点 它的父亲地点[1] --------- ----------------/ | \ 1 ---(城镇中心没有父亲)/ | \ 2 1[2] [3] [6] 3 1/ | \ 4 2/ | \ 5 8[4] [8] [9] 6 1/ \ 7 8/ \ 8 6[5] [7] 9 6以下为他们某次见面的安排:Bessie Jon Meeting Place-------- -------- ---------------2 7 14 2 21 1 14 1 17 5 89 5 6
输入第1行:两个数N,M代表一共有N个地方,B和J已经进行了M次见面第2..N-1行,每行一个数X,代表第i个地点的父亲为X再接下来M行,每行两个数,分别代表B和J当天准备去游玩的地方1<=N<=1000,1<=M<=1000
输出一共M行,每行一个数代表B和J当天见面的地方。样例输入9 6112818662 74 23 34 17 59 5
样例输出
123186
题解:LCA裸题
倍增版:#include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; const int N=1010; const int LOG=10; 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 n, m, p1, p2; int fa[N], f[N][15], dep[N]; void Build() { for( int i=2; i<=n; i++ ) Getin(fa[i]), f[i][0]=fa[i]; for( int j=1; j<=LOG; j++ ) for( int i=1; i<=n; i++ ) f[i][j]=f[ f[i][j-1] ][j-1]; } void Deep() { for( int i=2; i<=n; i++ ) { int t=i; while( t!=1 ) t=fa[t], dep[i]++; } } int getk( int r ,int k ) { for( int i=0; i<=LOG; i++ ) if( k&( 1<<i ) ) r=f[r][i]; return r; } int getd( int r, int d ) { return getk( r, dep[r]-d ); } 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( f[p1][i]!=f[p2][i] ) p1=f[p1][i], p2=f[p2][i]; return fa[p1]; } int main() { Getin(n); Getin(m); Build(); Deep(); for( int i=1; i<=m; i++ ) { Getin( p1 ); Getin( p2 ); printf( "%d\n", LCA_Find() ); } return 0; }
链剖版:#include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<cmath> #include<algorithm> using namespace std; const int N=1010; int n, m; 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 nodes{ int e, next; }edge[N<<1]; 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 LAC() { 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); Getin(m); for( int i=2; i<=n; i++ ) Getin( fa[i] ), Link( fa[i], i ); DFS1( 1, 1 ); top[1]=1; DFS2(1); for( int i=1; i<=m; i++ ) { Getin( p1 ); Getin( p2 ); printf( "%d\n", LAC() ); } return 0; }