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 <cstdio>
#include <iostream>
using namespace std;

const int MAXN = 1e5 + 5;

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

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

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

void add_e (int, int);
void add_q (int, int, int);
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;
        add_e (x, y); add_e (y, x);
    }
    for (int i = 1; i <= m; i++) {
        int x, y; cin >> x >> y;
        add_q (x, y, i);
        add_q (y, x, i);
    }
    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;
    e[len].next = head[x];
    head[x] = len;
}

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

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];
}
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页