洛谷 P3379 【模板】最近公共祖先(LCA)(树链剖分写法)

题目链接: P3379 【模板】最近公共祖先(LCA)

今天突然想到,树剖可以写LCA,就实现了一下,可以过,在这里存一下

代码

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;
#define mem(a, b) memset(a, b, sizeof(a))
typedef long long ll;
const int N = 5e5 + 10;
const int inf = 0x3f3f3f3f;
int n, m, s;
int fa[N], dep[N], siz[N], son[N], top[N];
int first[N], tot, cnt;
struct edge
{
    int v, next;
} e[N * 2];
void init()
{
    mem(first, -1);
    tot = 0;
    cnt = 0;
}
void add_edge(int u, int v)
{
    e[tot].v = v;
    e[tot].next = first[u];
    first[u] = tot++;
}
void dfs1(int u, int f, int deep)
{
    fa[u] = f;
    dep[u] = deep;
    siz[u] = 1;
    son[u] = 0;
    int maxson = -1;
    for (int i = first[u]; ~i; i = e[i].next)
    {
        int v = e[i].v;
        if (v == f)
            continue;
        dfs1(v, u, deep + 1);
        siz[u] += siz[v];
        if (siz[v] > maxson)
        {
            son[u] = v;
            maxson = siz[v];
        }
    }
}
void dfs2(int u, int topf)
{
    top[u] = topf;
    if (!son[u])
        return;
    dfs2(son[u], topf);
    for (int i = first[u]; ~i; i = e[i].next)
    {
        int v = e[i].v;
        if (v == fa[u] || v == son[u])
            continue;
        dfs2(v, v);
    }
}
int qlca(int x, int y)
{
    while (top[x] != top[y])
    {
        if (dep[top[x]] < dep[top[y]])
            swap(x, y);
        x = fa[top[x]];
    }
    return dep[x] < dep[y] ? x : y;
}
int main()
{
    //freopen("in.txt", "r", stdin);
    int u, v;
    scanf("%d%d%d", &n, &m, &s);
    init();
    for (int i = 1; i <= n - 1; i++)
    {
        scanf("%d%d", &u, &v);
        add_edge(u, v);
        add_edge(v, u);
    }
    dfs1(s, 0, 1);
    dfs2(s, s);
    while (m--)
    {
        scanf("%d%d", &u, &v);
        printf("%d\n", qlca(u, v));
    }

    return 0;
}

你可能感兴趣的:(【最近公共祖先LCA】,【树链剖分】)