第一节 最近公共祖先

倍增

#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 50;

int n, m, s;
int head[N], tot;
int lg[N]; // log2(i)+1
int fa[N][22], dep[N];
struct Edge {
    int nex, to;
}eg[N << 1];
void add(int a, int b) {
    eg[++tot] = (Edge){head[a], b};
    head[a] = tot;
}
void init() {
    for(int i = 1; i <= n; i++) {
        lg[i] = lg[i-1] + ((1 << lg[i-1]) == i);
    }
}
void dfs(int u, int F) {
    dep[u] = dep[F] + 1;
    fa[u][0] = F;
    for(int i = 1; i <= lg[dep[u]]; i++) {
        fa[u][i] = fa[fa[u][i-1]][i-1];
    }
    for(int i = head[u]; i; i = eg[i].nex) {
        int to = eg[i].to;
        if(to != F) dfs(to, u);
    }
}
int lca(int x, int y) {
    if (dep[x] < dep[y]) swap(x, y);
    while (dep[x] > dep[y]) x = fa[x][lg[dep[x]-dep[y]] - 1];
    if (x == y) return x;
    for (int i = lg[dep[x]] - 1; 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, a, b; i < n; i++) {
        scanf("%d%d", &a, &b);
        add(a, b); add(b, a);
    }
    init(); dfs(s, 0);
    for(int i = 1, a, b; i <= m; i++) {
        scanf("%d%d", &a, &b);
        printf("%d\n", lca(a, b));
    }
    return 0;
}

树链剖分

#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 50;
int n, m, s;

int head[N], tot;
struct Edge {
    int nex, to;
}e[N << 1];
void add(int a, int b) {
    e[++tot] = (Edge){head[a], b};
    head[a] = tot;
}

struct Node {
    int dep, fa, sz;
    int mson, top;
}nd[N];
void dfs1(int rt, int fa, int dep) {
    nd[rt].dep = dep; nd[rt].fa = fa; nd[rt].sz = 1;
    int mson = -1;
    for (int i = head[rt]; i; i = e[i].nex) {
        int to = e[i].to;
        if (to == fa) continue;
        dfs1(to, rt, dep + 1);
        nd[rt].sz += nd[to].sz;
        if (nd[to].sz > mson) {
            mson = nd[to].sz;
            nd[rt].mson = to;
        }
    }
}
void dfs2(int rt, int tp) {
    nd[rt].top = tp;
    if (!nd[rt].mson) return;
    dfs2(nd[rt].mson, tp);
    for (int i = head[rt]; i; i = e[i].nex) {
        int to = e[i].to;
        if (to == nd[rt].fa || to == nd[rt].mson) continue;
        dfs2(to, to);
    }
}

#define topx nd[x].top
#define topy nd[y].top
int lca(int x, int y) {
    while (topx != topy) {
        if(nd[topx].dep < nd[topy].dep) y = nd[topy].fa;
        else x = nd[topx].fa;
    }
    return nd[x].dep < nd[y].dep ? x : y;
}

int main(int argc, const char * argv[]) {
    scanf("%d%d%d", &n, &m, &s);
    for (int i = 1, a, b; i < n; i++) {
        scanf("%d%d", &a, &b);
        add(a, b); add(b, a);
    }
    dfs1(s, 0, 1); dfs2(s, s);
    for (int i = 1, a, b; i <= m; i++) {
        scanf("%d%d", &a, &b);
        printf("%d\n", lca(a, b));
    }
    return 0;
}

例题: 洛谷P3292 [SCOI2016]幸运数字

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇