【模板】最近公共祖先(LCA)

题目

这,大概是我在CSP前最后的一篇模板题了吧。

时隔一年,昨天又一次成功地打对了LCA,可海星。
这里用的是倍增的写法。
Code:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
using namespace std;
//Mystery_Sky
//
#define M 500001
#define INF 0x3f3f3f3f
#define ll long long
inline int read()
{
	int x=0, f=1; char c=getchar();
	while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
	while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
	return x*f;
}
struct Edge{
	int next, to;
}edge[M<<1];
int n, m, cnt, t, s;
int head[M], d[M], f[M][30];
queue <int> q;
inline void add_edge(int u, int v) {edge[++cnt].to = v; edge[cnt].next = head[u]; head[u] = cnt;}

inline void bfs()
{
	d[s] = 1;
	q.push(s);
	while(!q.empty()) {
		int x = q.front(); q.pop();
		for(int i = head[x]; i; i = edge[i].next) {
			int y = edge[i].to;
			if(d[y]) continue;
			d[y] = d[x] + 1;
			f[y][0] = x;
			for(int j = 1; j <= t; j++) 
				f[y][j] = f[f[y][j-1]][j-1];
			q.push(y); 
		}
	} 
	return;
}

inline int lca(int x, int y)
{
	if(d[x] > d[y]) swap(x, y);
	for(int i = t; i >= 0; i--) 
		if(d[f[y][i]] >= d[x]) y = f[y][i];
	if(x == y) return x;
	for(int i = t; i >= 0; i--) 
		if(f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];
	return f[x][0];
}
int main() {
	n = read(), m = read(), s = read();
	t = (int)(log(n) / log(2));
	for(int i = 1; i <= n-1; i++) {
		int u = read(), v = read();
		add_edge(u, v); add_edge(v, u);
	}
	bfs();
	for(int i = 1; i <= m; i++) {
		int x = read(), y = read();
		printf("%d\n", lca(x, y));
	}
	return 0;
}
posted @ 2019-11-13 12:27  Mystery_Sky  阅读(230)  评论(0编辑  收藏  举报