您的位置:首页 > 其它

[LCA] POJ 1330

2017-11-30 22:02 260 查看
最基本的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 >
4000
= 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: