洛谷 #3379. 【模板】LCA

倍增

用\(f[cur][i]\)表示\(cur\)的第\(\ 2^i\)個祖先

\(f[cur][i] = f[f[cur][i-1]][i-1]\)

因爲\(\ 2{i-1}+2{i-1}=2^i\)

調試記錄

\(f[cur][0] = fa\)

#include <cstdio>
#include <algorithm>
#define maxn 500005
#define logn 25
using namespace std;

struct node{
	int to, nxt;
}e[maxn << 1];
int head[maxn], tot = 0;
void addedge(int u, int v){
	e[++tot].to = v, e[tot].nxt = head[u];
	head[u] = tot;
}
int n, m, root;
int dep[maxn], f[maxn][logn + 5];
void dfs(int cur, int fa){
	dep[cur] = dep[fa] + 1;
	f[cur][0] = fa;
	for (int i = 1; (1 << i) <= dep[cur]; i++)
		f[cur][i] = f[f[cur][i - 1]][i - 1];
	for (int i = head[cur]; i; i = e[i].nxt){
		if (e[i].to != fa) dfs(e[i].to, cur);
	}
}
int LCA(int u, int v){
	if (dep[u] > dep[v]) swap(u, v);
	for (int i = logn; i >= 0; i--)
		if (dep[u] <= dep[v] - (1 << i)) v = f[v][i];
	if (u == v) return u;
	for (int i = logn; i >= 0; i--)
		if (f[u][i] != f[v][i]) u = f[u][i], v = f[v][i];
	return f[u][0];
}
int main(){
	scanf("%d%d%d", &n, &m, &root);
	for (int u, v, i = 1; i < n; i++){
		scanf("%d%d", &u, &v);
		addedge(u, v), addedge(v, u);
	}
	dfs(root, 0);
	while (m--){ int u, v;
		scanf("%d%d", &u, &v);
		printf("%d\n", LCA(u, v));
	}
	return 0;
}

Tarjan

題解

#include <cstdio>

#define maxn 500005

using namespace std;

struct node_edge{
	int next, to, LCA;
}e[maxn * 2], q[maxn * 2];

int etot = 0, qtot = 1, efirst[maxn], qfirst[maxn], n, m, root;
int f[maxn];

int GetFather(int x){
	if (f[x] == x) return x;
	else return (f[x] = GetFather(f[x]));
}

void eAddEdge(int x, int y){
	etot++;
	e[etot].to = y;
	e[etot].next = efirst[x];
	efirst[x] = etot;
}

void qAddEdge(int x, int y){
	qtot++;
	q[qtot].to = y;
	q[qtot].next = qfirst[x];
	qfirst[x] = qtot;
}

bool vis[maxn];

void dfs(int x){
	vis[f[x] = x] = true;
	for (int i = efirst[x]; i; i = e[i].next){
		if (!vis[e[i].to]){
			dfs(e[i].to);
			f[e[i].to] = x;
		}
	}
	for (int i = qfirst[x]; i; i = q[i].next){
		if (vis[q[i].to]) q[i^1].LCA = q[i].LCA = GetFather(q[i].to);
	}
}

int main(){
	scanf("%d%d%d", &n, &m, &root);
	
	for (int a, b, i = 1; i < n; i++){
		scanf("%d%d", &a, &b);
		eAddEdge(a, b); eAddEdge(b, a); /*1*/
	}
	
	for (int a, b, i = 1; i <= m; i++){
		scanf("%d%d", &a, &b);
		qAddEdge(a, b); qAddEdge(b, a);
	}
	dfs(root);
	for (int i = 1; i <= m; i++) printf("%d\n", q[i * 2].LCA);
	
	return 0;
} 
//https://www.luogu.org/problemnew/show/P3379
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章