题目描述
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 1
4 2 2
1 1 1
4 1 1
7 5 8
9 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 6
1
1
2
8
1
8
6
6
2 7
4 2
3 3
4 1
7 5
9 5
样例输出
1
2
3
1
8
6
题解: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;
}