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

女生的网名这么多〃 提交于 2019-12-04 08:19:24

题目

这,大概是我在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;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!