最基本的LCA啦~
用二分的方法做的
和书上代码一模一样。。。
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
using namespace std;
const int max_n = 10000;
const int max_log_n = 14; // (1 << max_log_n) > max_n
int n;
int root; //根节点
int dep[ max_n ];
int par[ max_log_n ][ max_n ]; //向上走2^k步所到的节点
vector<int> child[ max_n ]; //图的邻接表
void dfs ( int u, int p, int d ) {
dep[ u ] = d;
for ( int i = 0; i < int( child[ u ].size () ); i++ ) {
int v = child[ u ][ i ];
if ( v != p ) {
dfs ( v, u, d + 1 );
}
}
}
void build () {
// 预处理 par[0][u] and dep[u]
dfs ( root, -1, 0 );
// par[i][u]
for ( int i = 0; i + 1 < max_log_n; i++ ) {
for ( int u = 0; u < n; u++ ) {
if ( par[ i ][ u ] == -1 )
par[ i + 1 ][ u ] = -1;
else
par[ i + 1 ][ u ] = par[ i ][ par[ i ][ u ] ];
}
}
}
int lca ( int u, int v ) {
if ( dep[ u ] > dep[ v ] )
swap ( u, v );
// u v 走到同一深度
int diff = dep[ v ] - dep[ u ];
for ( int i = 0; i < max_log_n; i++ ) {
if ( diff & ( 1 << i ) ) {
v = par[ i ][ v ];
}
}
if ( u == v )
return u;
//二分法计算LCA
for ( int i = max_log_n - 1; i >= 0; i-- ) {
if ( par[ i ][ u ] != par[ i ][ v ] ) {
u = par[ i ][ u ];
v = par[ i ][ v ];
}
}
return par[ 0 ][ u ];
}
int main () {
int tc;
scanf ( "%d", &tc );
while ( tc-- ) {
scanf ( "%d", &n );
//一个新东西
fill ( dep, dep + n, -1 );
for ( int i = 0; i < max_log_n; i++ )
fill ( par[ i ], par[ i ] + n, -1 );
for ( int i = 0; i < n; i++ )
child[ i ].clear ();
for ( int i = 0; i < n - 1; i++ ) {
int u, v;
scanf ( "%d %d", &u, &v );
u--;
v--;
par[ 0 ][ v ] = u;
child[ u ].push_back ( v );
}
root = -1;
for ( int u = 0; u < n; u++ ) {
if ( par[ 0 ][ u ] == -1 ) {
root = u;
break;
}
}
build ();
int u, v;
scanf ( "%d %d", &u, &v );
u--;
v--;
printf ( "%d\n", lca ( u, v ) + 1 );
}
return 0;
}