1.树上倍增

#include <queue>
#include <cstdio>
using namespace std;

const int MAXN = 1e5 + 5;
const int MAXTEP = 45;

int n, m;
int depth[MAXN], f[MAXN][MAXTEP];

struct edge {
int to, next;
}e[MAXN * 2];

void build ();

int lca (int, int);

int main () {
scanf ("%d %d", &n, &m);
for (int i = 1; i < n; i++) {
int x, y; scanf ("%d %d", &x, &y);
}
build ();
for (int i = 1; i <= m; i++) {
int x, y; scanf ("%d %d", &x, &y);
printf ("%d\n", lca (x, y));
}
return 0;
}

void add (int x, int y) {
e[++len].to = y;
}

void build () {
queue <int> q; q.push (1); depth[1] = 1;
while (!q.empty ()) {
int u = q.front (); q.pop ();
for (int i = head[u]; i; i = e[i].next) {
int v = e[i].to;
if (depth[v]) continue;
depth[v] = depth[u] + 1; q.push (v);
f[v][0] = u;
for (int j = 1; j < MAXTEP; j++) {
f[v][j] = f[f[v][j - 1]][j - 1];
}
}
}
}

int lca (int x, int y) {
if (depth[x] > depth[y]) swap (x, y);

for (int i = MAXTEP - 1; i >= 0; i--) {
int v = f[y][i];
if (depth[v] >= depth[x])
y = v;
}

if (x == y) return x;

for (int i = MAXTEP - 1; i >= 0; i--) {
int v = f[x][i], vv = f[y][i];
if (v != vv)
x = v, y = vv;
}
return f[x][0];
}


2.Tarjan

#include <cstdio>
#include <iostream>
using namespace std;

const int MAXN = 1e5 + 5;

int n, m;
int fa[MAXN], vis[MAXN], ans[MAXN];

struct edge {
int to, next;
}e[MAXN * 2];

struct edge_q {
int to, next, index;
}e_q[MAXN * 2];

void Tarjan (int);
void MakeSet ();

int FindSet (int);

int main () {
cin >> n >> m; MakeSet ();
for (int i = 1; i < n; i++) {
int x, y; cin >> x >> y;
}
for (int i = 1; i <= m; i++) {
int x, y; cin >> x >> y;
}
Tarjan (1);
for (int i = 1; i <= m; i++) {
printf ("%d\n", ans[i]);
}
return 0;
}

void add_e (int x, int y) {
e[++len].to = y;
}

void add_q (int x, int y, int index) {
e_q[++len_q].to = y;
e_q[len_q].index = index;
}

void Tarjan (int u) {
//	printf ("u = %d\n", u);
//	for (int i = 1; i <= n; i++) printf ("%d ", vis[i]); printf ("\n");
vis[u] = 1;
for (int i = head[u]; i; i = e[i].next) {
int v = e[i].to;
if (vis[v]) continue;
Tarjan (v);
fa[v] = u;
}
vis[u] = 2;
for (int i = head_q[u]; i; i = e_q[i].next) {
int v = e_q[i].to, index = e_q[i].index;
if (vis[v] == 2)
ans[index] = FindSet (v);
}
}

void MakeSet () {
for (int i = 1; i <= n; i++) {
fa[i] = i;
}
}

int FindSet (int x) {
if (fa[x] != x) {
fa[x] = FindSet (fa[x]);
}
return fa[x];
}


02-18 764

10-18 1万+
08-06 9439
08-30 1604
08-06 3020
01-28 586
06-06
03-30
11-01
01-27
01-16 3509