参见topcoder的算法教程,Range Minimum Query and Lowest Common Ancestor
JOJ 一个题目:
2408 Beautiful girl, 题意:一颗树,给定三个顶点A、B、C,判断A与B之间的路径是否可以经过C
代码:
/*
* LCA->RMQ
*/
#include < cstdio >
#include < vector >
#include < cmath >
using namespace std;
#define MY_MAX 50010
vector < int > graph[MY_MAX];
void read( int n){
int i, u, v;
for (i = 0 ; i < n; ++ i)
if ( ! graph[i].empty())
graph[i].clear();
for (i = 1 ; i < n; ++ i){
scanf( " %d %d " , & u, & v);
graph[u].push_back(v);
graph[v].push_back(u);
}
}
int E[MY_MAX * 2 ]; // E[i] is the label of i-th visited node in the tour
int L[MY_MAX * 2 ]; // L[i] is the level of node E[i]
int H[MY_MAX]; // the index of the first occurrence of node i in E
bool visited[MY_MAX];
void DFS( int u, int d, int & k){
visited[u] = true ;
E[k] = u;
L[k] = d;
H[u] = k;
++ k;
int v;
for (size_t i = 0 ; i < graph[u].size(); ++ i){
v = graph[u][i];
if ( ! visited[v]){
DFS(v, d + 1 , k);
E[k] = u;
L[k] = d;
++ k;
}
}
}
int M[MY_MAX * 2 ][ 20 ]; // 存储的索引
void preprocess( int a[], int n){
int i, j;
// initialize for the intervals with length 1
for (i = 0 ; i < n; ++ i)
M[i][ 0 ] = i;
// compute values from smaller to bigger intervals
for (j = 1 ; 1 << j <= n; ++ j){
for (i = 0 ; i + ( 1 << j) - 1 < n; ++ i)
if (a[M[i][j - 1 ]] < a[M[i + ( 1 << (j - 1 ))][j - 1 ]])
M[i][j] = M[i][j - 1 ];
else
M[i][j] = M[i + ( 1 << (j - 1 ))][j - 1 ];
}
}
int RMQ( int a[], int i, int j){
if (i > j)
swap(i, j);
int k;
k = int (log(j - i + 1 ) / log( 2.0 ));
if (a[M[i][k]] < a[M[j - ( 1 << k) + 1 ][k]])
return M[i][k];
else
return M[j - ( 1 << k) + 1 ][k];
}
int main(){
// freopen("in", "r", stdin);
int n, m, k, case_num = 1 ;
while (scanf( " %d " , & n) != EOF){
read(n);
for (k = 0 ; k < n; ++ k)
visited[k] = false ;
k = 0 ;
DFS( 0 , 0 , k);
preprocess(L, 2 * n - 1 );
int a, b, c;
int lab, lac, lbc;
if (case_num != 1 )
printf( " \n " );
printf( " Case %d:\n " , case_num ++ );
scanf( " %d " , & m);
for (k = 0 ; k < m; ++ k){
scanf( " %d %d %d " , & a, & b, & c);
lab = E[RMQ(L, H[a], H[b])];
lac = E[RMQ(L, H[a], H[c])];
lbc = E[RMQ(L, H[b], H[c])];
if (a == c || b == c || (lab == lac && lbc == c)
|| (lab == lbc && lac == c))
printf( " Yes\n " );
else
printf( " No\n " );
}
}
}