lca模板

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];

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

void add (int, int);
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);
		add (x, y); add (y, x);
	}
	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;
	e[len].next = head[x];
	head[x] = len;
}

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 <cmath>
#include <vector>
#include <cstdio>
#include <cstdlib> 
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define fi first
#define se second
#define db double
#define LL long long
#define ULL unsigned long long
#define PII pair <int, int>
#define MP(x,y) make_pair (x, y)
#define rep(i,j,k) for (int i = (j); i <= (k); i++)
#define per(i,j,k) for (int i = (j); i >= (k); i--)

template <typename T> T Max (T x, T y) { return x > y ? x : y; }
template <typename T> T Min (T x, T y) { return x < y ? x : y; }
template <typename T> T Abs (T x) { return x > 0 ? x : -x; }
template <typename T>
void read (T &x) {
	x = 0; T f = 1;
	char ch = getchar ();
	while (ch < '0' || ch > '9') {
		if (ch == '-') f = -1;
		ch = getchar ();
	}
	while (ch >= '0' && ch <= '9') {
		x = (x << 3) + (x << 1) + ch - '0';
		ch = getchar ();
	}
	x *= f;
}
char For_Print[25];
template <typename T>
void write (T x) {
	if (x == 0) { putchar ('0'); return; }
	if (x < 0) { putchar ('-'); x = -x; }
	int poi = 0;
	while (x) {
		For_Print[++poi] = x % 10 + '0';
		x /= 10;
	}
	while (poi) putchar (For_Print[poi--]);
}
template <typename T>
void print (T x, char ch) {
	write (x); putchar (ch);
}

const int Maxn = 5 * 1e5;
const int Maxk = 25;

vector <int> g[Maxn + 5];
vector <PII> q[Maxn + 5];
void add (int x, int y) { g[x].push_back (y); }
void add_q (int x, int y, int id) { q[x].push_back (MP (y, id)); }

int n, m, rt;

int fa[Maxn + 5];
void MakeSet () { rep (i, 1, Maxn) fa[i] = i; }
int FindSet (int x) { return (fa[x] != x) ? fa[x] = FindSet (fa[x]) : x; }
bool vis[Maxn + 5];
int ans[Maxn + 5];
void Tarjan (int u, int _fa) {
	for (auto v : g[u]) {
		if (v == _fa) continue;
		Tarjan (v, u);
		fa[v] = u;
	}
	vis[u] = 1;
	for (auto i : q[u]) {
		int v = i.fi, id = i.se;
		if (vis[v] == 1)
			ans[id] = FindSet (v);
	}
}

int main () {
// 	freopen ("C:\\Users\\Administrator\\Desktop\\lihan\\1.in", "r", stdin);
// 	freopen ("C:\\Users\\Administrator\\Desktop\\lihan\\1.out", "w", stdout);

	MakeSet ();
	
	read (n); read (m); read (rt);
	rep (i, 1, n - 1) {
		int x, y; read (x); read (y);
		add (x, y); add (y, x);
	}
	rep (i, 1, m) {
		int x, y; read (x); read (y);
		add_q (x, y, i); add_q (y, x, i);
	}

	Tarjan (rt, -1);
	rep (i, 1, m) {
		print (ans[i], '\n');
	}
	return 0;
}
posted @ 2020-12-04 12:40  C2022lihan  阅读(5)  评论(0编辑  收藏  举报