LCA是一个深搜的过程
LCA(u)的作用是,使所有已经通过深搜搜到了的u的子节点都指向u。
又因为如果求a,b的LCA(假设为c),那么一定是先从根搜到c,然后向下先搜到一个节点(假设为a),然后回溯到c,然后向下搜到b,这是,a已经指向c,答案自然就是father[a]
这题用到了并查集,但是我把其中的rank去掉了
AC代码如下:
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
struct Edge{
int to, next;
};
int father[11000];
int head[11000], tot;
Edge edge[22000];
int T, N, mark[11000], color[11000];
int a, b;
void add_edge( int a, int b ){
edge[tot].to = b;
edge[tot].next = head[a];
head[a] = tot++;
}
int make_set( int u ){
father[u] = u;
return 0;
}
int find_set( int u ){
if( u != father[u] ){
father[u] = find_set( father[u] );
}
return father[u];
}
int union_set( int u, int v ){
int x = find_set( u );
int y = find_set( v );
if( x != y ) father[y] = x;
return 0;
}
void LCA( int u ){
make_set( u );
for( int i = head[u]; i != -1; i = edge[i].next ){
LCA( edge[i].to );
union_set( u, edge[i].to );
}
color[u] = 1;
if( u == a ){
if( color[b] ){
printf( "%d\n", find_set( b ) );
}
}else if( u == b ){
if( color[a] ){
printf( "%d\n", find_set( a ) );
}
}
}
int main(){
scanf( "%d", &T );
while( T-- ){
scanf( "%d", &N );
memset( mark, 0, sizeof( mark ) );
memset( head, -1, sizeof( head ) );
memset( color, 0, sizeof( color ) );
tot = 0;
for( int i = 1; i < N; i++ ){
int temp1, temp2;
scanf( "%d%d", &temp1, &temp2 );
add_edge( temp1, temp2 );
mark[temp2]++;
}
scanf( "%d%d", &a, &b );
for( int i = 1; i <= N; i++ ){
if( mark[i] == 0 ){
LCA( i );
break;
}
}
}
return 0;
}