洛谷P3379 【模板】最近公共祖先(LCA)
倍增算法
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
inline int read() {
int x = 0, tmp = 1; char ch = getchar();
while( ch < '0' || ch > '9' ) { if( ch == '-' ) tmp = -1; ch = getchar(); }
while( ch >= '0' && ch <= '9' ) { x = x * 10 + ch - '0'; ch = getchar(); }
return x * tmp;
}
inline void write( int k ) {
if( k < 0 ) { putchar( '-' ); k = -k; }
if( k > 9 ) write( k / 10 );
putchar( k % 10 + '0' );
}
struct Point {
int to, next;
} edge[1100000];
int head[510000], idx = 0, dep[510000], f[510000][22];
bool vis[510000];
inline void ade( int u, int v ) {
edge[++ idx].to = v;
edge[idx].next = head[u];
head[u] = idx;
}
void dfs( int x ) {
vis[x] = 1;
for( int i = 1 ; i <= 20 ; ++ i ) {
if( dep[x] < ( 1 << i ) ) break;
f[x][i] = f[f[x][i - 1]][i - 1];
}
for( int i = head[x] ; i != -1 ; i = edge[i].next ) {
int now = edge[i].to;
if( !vis[now] ) {
dep[now] = dep[x] + 1;
f[now][0] = x;
dfs( now );
}
}
}
int lca( int u, int v ) {
if( dep[u] > dep[v] ) swap( u, v );
for( int i = 20 ; i >= 0 ; -- i ) if( dep[f[v][i]] >= dep[u] ) v = f[v][i];
if( u == v ) return u;
for( int i = 20 ; i >= 0 ; -- i ) if( f[v][i] != f[u][i] ) v = f[v][i], u = f[u][i];
return f[u][0];
}
int main() {
memset( head, -1, sizeof( head ) );
memset( f, 0, sizeof( f ) );
memset( dep, 0, sizeof( dep ) );
memset( vis, 0, sizeof( vis ) );
int N = read(), M = read(), root = read();
for( int i = 1 ; i < N ; ++ i ) {
int x = read(), y = read();
ade( x, y ); ade( y, x );
}
dep[root] = 1;
dfs( root );
for( int i = 1 ; i <= M ; ++ i ) {
int x = read(), y = read();
write( lca( x, y ) );
putchar( '\n' );
}
return 0;
}
tarjan算法
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
inline int read() {
int x = 0, tmp = 1; char ch = getchar();
while( ch < '0' || ch > '9' ) { if ( ch == '-' ) tmp = -1; ch = getchar(); }
while( ch >= '0' && ch <= '9' ) { x = x * 10 + ch - '0'; ch = getchar(); }
return x * tmp;
}
struct Point {
int to, next;
} edge[1100000];
int head[510000], idx = 0;
bool vis[510000];
struct ansPoint {
int to, next, num;
} ansedge[1100000];
int anshead[510000], ansidx = 0, ans[510000], group[510000];
inline void ade( int u, int v ) {
edge[++ idx].to = v;
edge[idx].next = head[u];
head[u] = idx;
}
inline void ansade( int u, int v, int num ) {
ansedge[++ ansidx].to = v;
ansedge[ansidx].next = anshead[u];
ansedge[ansidx].num = num;
anshead[u] = ansidx;
}
int find( int x ) {
int pre = x, y;
while( x != group[x] ) x = group[x];
while( pre != group[pre] ) {
y = group[pre];
group[pre] = x;
pre = y;
}
return x;
}
void dfs( int x ) {
vis[x] = 1;
group[x] = x;
for( int i = head[x] ; i != -1; i = edge[i].next ) {
int now = edge[i].to;
if( !vis[now] ) {
dfs( now );
group[now] = x;
}
}
for( int i = anshead[x] ; i != -1 ; i = ansedge[i].next ) {
int now = ansedge[i].to, num = ansedge[i].num;
if( vis[now] ) ans[num] = find( now );
}
}
int main() {
memset( head, -1, sizeof( head ) );
memset( anshead, -1, sizeof( anshead ) );
int N = read(), M = read(), root = read();
for( int i = 1 ; i < N ; ++ i ) {
int x = read(), y = read();
ade( x, y ); ade( y, x );
}
for( int i = 1 ; i <= M ; ++ i ) {
int x = read(), y = read();
ansade( x, y, i ); ansade( y, x, i );
}
dfs( root );
for( int i = 1 ; i <= M ; ++ i ) printf( "%d\n", ans[i] );
}