DFS 序在祖先问题的使用

祖孙询问

此问题可以用 LCA 来解决,但是 LCA 的码量大,而且可能容易写挂,尤其是像我这种蒟蒻

如果卡时间的话有可能倍增/重链剖分 LCA 都要挂掉,这时候就是 DFS 序发挥作用的时候了。


拿一个计数器。在遍历到每一个节点的时候,我们在进入它的时候记录一下,在离开它的时候也记录一下,在记录完成后就得到了一个树的 DFS 序

代码如下:

/*
LOJ10135
https://loj.ac/p/10135
*/
#include <iostream>
#include <vector>
using namespace std;
const int maxn = 4e4 + 5;

int n, m, root;
vector<int> G[maxn];
int ti;
int in[maxn], out[maxn];

void dfs(int x) {
    if(in[x] != 0) return;
    in[x] = ++ti;
    for(int to : G[x]) dfs(to);
    out[x] = ++ti;
}

int ask(int x, int y) {

    return in[x] < in[y] && in[y] < out[y] && out[y] < out[x];
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin >> n;
    for(int i = 1, u, v; i <= n; i++) {
        cin >> u >> v;
        if(v == -1) {
            root = u;
            continue;
        }
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dfs(root);
    cin >> m;
    for(int i = 1, u, v; i <= m; i++) {
        cin >> u >> v;
        if(ask(u, v)) cout << 1 << "\n";
        else if(ask(v, u)) cout << 2 << "\n";
        else cout << 0 << "\n";
    }
    return 0;
} 

//106ms

与倍增 LCA 相比,快了些许

祖孙询问(LOJ10135)
https://vjudge.csgrandeur.cn/contest/584212#problem/D
*/
#include <iostream>
#include <vector>
using namespace std;
const int maxn = 4e4 + 5;
const int maxk = 20; 

int n, root, m;
vector<int> G[maxn];

int fa[maxk][maxn];
int depth[maxn];

void dfs(int x, int f) {
    fa[0][x] = f;
    depth[x] = depth[f] + 1;
    for (int i = 1; i < maxk; i++) {
        fa[i][x] = fa[i - 1][fa[i - 1][x]];
    }
    for (auto to : G[x]) {
        if (to == f)
            continue;
        dfs(to, x);
    }
}

int LCA(int x, int y) {
    if (depth[x] < depth[y])
        swap(x, y);
    for (int i = maxk - 1; i >= 0; i--) {
        if (depth[fa[i][x]] >= depth[y])
            x = fa[i][x];
    }
    if (x == y)
        return x;
    for (int i = maxk - 1; i >= 0; i--) {
        if (fa[i][x] != fa[i][y]) {
            x = fa[i][x];
            y = fa[i][y];
        }
    }
    return fa[0][x];
}

int main() {
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    cin >> n;
    for(int i = 1, u, v; i <= n; i++) {
        cin >> u >> v;
        if(v == -1) {root = u; continue;}
        G[u].push_back(v);
        G[v].push_back(u);
    }
    cin >> m;
    int x, y;
    dfs(root, 0);
    while(m--) {
        cin >> x >> y;
        int lca = LCA(x, y);
        if(lca == x) cout << "1\n";
        else if(lca == y) cout << "2\n";
        else cout << "0\n";
    }
}
//130ms

因为在使用 DFS 序解决问题时,它的查询是常数时间复杂度,所以说要快很多。

当然,DFS 序也可以用于LCA问题中,详见这篇文章

暂无评论

发送评论 编辑评论


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