图论 - 树论 - LCA

图论 - 树论 - LCA

朴素 题目链接:http://poj.org/problem?id=1330

倍增 、 树剖 题目链接: https://www.luogu.org/problem/P3379

朴素代码:

//#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

const int N = 10010;

int T, n, vis[N];

int tot, head[N], nxt[N << 1], to[N << 1];

void add(int x, int y) {
	to[ ++ tot] = y;
	nxt[tot] = head[x];
	head[x] = tot;
}

int fa[N], dep[N];

void dfs(int now, int pre) {
	dep[now] = dep[pre] + 1;
	fa[now] = pre;
	for (int i = head[now]; i; i = nxt[i]) {
		if (to[i] == pre) {
			continue ;
		}
		dfs(to[i], now);
	}
}

int LCA(int x, int y) {
	if (dep[x] < dep[y]) {
		swap(x, y);
	}
	while (dep[x] > dep[y]) {
		x = fa[x];
	}
	while (x != y) {
		x = fa[x], y = fa[y];
	}
	return x;
}

void init() {
	tot = 0;
	memset(head, 0, sizeof head);
	memset(vis, 0, sizeof vis);
	memset(dep, 0, sizeof dep);
}

int main() {
	scanf("%d", &T);
	while (T -- ) {
		init();
		tot = 0;
		scanf("%d", &n);
		for (int i = 1; i <= n - 1; i ++ ) {
			int a, b;
			scanf("%d%d", &a, &b);
			vis[b] = 1;
			add(a, b);
		}
		int root;
		for (int i = 1; i <= n; i ++ ) {
			if (! vis[i]) {
				root = i;
				break ;
			}
		}
		dfs(root, root);
		int qa, qb;
		scanf("%d%d", &qa, &qb);
		printf("%d\n", LCA(qa, qb));		
	}
	return 0;
}

倍增LCA:

// #include <bits/stdc++.h>

#include <iostream>
#include <cstdio>
#include <algorithm>

using namespace std;

const int N = 500500;

int n, m, s;

int tot, to[N << 1], nxt[N << 1], head[N];

void add(int x, int y) {
	to[ ++ tot] = y;
	nxt[tot] = head[x];
	head[x] = tot;
}

int fa[N][25], dep[N];

void dfs(int pos, int pre) {
	fa[pos][0] = pre;
	dep[pos] = dep[pre] + 1;
	for (int i = 1; i <= 20; i ++ ) {
		if ((1 << i) >= dep[pos]) {
			break ;
		}
		fa[pos][i] = fa[fa[pos][i - 1]][i - 1];
	}
	for (int i = head[pos]; i; i = nxt[i]) {
		if (to[i] != pre) {
			dfs(to[i], pos);
		}
	}
}

int lca(int x, int y) {
	if (dep[x] < dep[y]) {
		swap(x, y);
	}
	for (int i = 20; i >= 0; i -- ) {
		if (dep[fa[x][i]] >= dep[y]) {
			x = fa[x][i];
		}
	}
	if (x == y) {
		return x;
	}
	for (int i = 20; i >= 0; i -- ) {
		if (fa[x][i] != fa[y][i]) {
			x = fa[x][i];
			y = fa[y][i];
		}
	}
	return fa[x][0];
}

int main() {
	scanf("%d%d%d", &n, &m, &s);
	for (int i = 1; i <= n - 1; i ++ ) {
		int a, b;
		scanf("%d%d", &a, &b);
		add(a, b);
		add(b, a);
	}
	dfs(s, 0);
	for (int i = 1; i <= m; i ++ ) {
		int a, b;
		scanf("%d%d", &a, &b);
		printf("%d\n", lca(a, b));
	}
	return 0;
}

树剖LCA:

#include <bits/stdc++.h>

using namespace std;

const int N = 500010;

int n, m, s;

int tot, head[N], to[N << 1], nxt[N << 1];

int dep[N], siz[N], fa[N], son[N], top[N];

void add(int x, int y) {
	to[ ++ tot] = y;
	nxt[tot] = head[x];
	head[x] = tot; 
}

void dfs1(int x) {
	dep[x] = dep[fa[x]] + 1;
	siz[x] = 1;
	for (int i = head[x]; i; i = nxt[i]) {
		if (to[i] == fa[x]) {
			continue ;
		}
		fa[to[i]] = x;
		dfs1(to[i]);
		siz[x] += siz[to[i]];
		if (! son[x] || siz[son[x]] < siz[to[i]]) {
			son[x] = to[i];
		}
	}
}

void dfs2(int x, int fir) {
	top[x] = fir;
	if (son[x]) {
		dfs2(son[x], fir);
	}
	for (int i = head[x]; i; i = nxt[i]) {
		int v = to[i];
		if (v == fa[x] || v == son[x]) {
			continue ;
		}
		dfs2(v, v);
	}
}

int LCA(int x, int y) {
	while (top[x] != top[y]) {
		if (dep[top[x]] >= dep[top[y]]) {
			x = fa[top[x]];
		}
		else {
			y = fa[top[y]];	
		}
	}
	if (dep[x] > dep[y]) {
		return y;
	}
	else {
		return x;
	}
}

int main() {
	scanf("%d%d%d", &n, &m, &s);
	for (int i = 1; i <= n - 1; i ++ ) {
		int a, b;
		scanf("%d%d", &a, &b);
		add(a, b);
		add(b, a);
	}
	dfs1(s);
	dfs2(s, s);
	for (int i = 1; i <= m; i ++ ) {
		int a, b;
		scanf("%d%d", &a, &b);
		printf("%d\n", LCA(a, b));
	}
	return 0;
}
posted @ 2019-11-15 00:08  筱柒_Littleseven  阅读(124)  评论(0编辑  收藏  举报