DFS 序总结

本文详细介绍了深度优先搜索(DFS)序和欧拉序列的概念、特点以及它们在树结构中处理子树统计和求解最近公共祖先(LCA)问题的性质。DFS序中每个节点出现两次,而欧拉序则记录了节点进入和离开的顺序,两者在路径上的节点计数规律揭示了节点间的祖先关系。同时,文章还提到了DFN序和如何通过区间统计来辅助树的分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

DFS 序

一、 DFS 序

1. 定义

对树进行深度优先搜索遍历时,对于每个节点,在刚进入递归后及即将回溯前各记录一次该点的编号,得到的最后产生的长度为 2N2N2N 的节点序列为 DFS 序;

void dfs(int i) {
    d[++len] = i;
    flag[i] = true;
    for (int t = 0; t < g[i].size(); t++) {
        int v = g[i][t];
        if (!flag[v]) {
            dfs(v);
        }
    }
    d[++len] = i;
    return;
}

2. 特点

  1. 每个节点 xxx 的编号在序列恰好存在两次;

  2. 设两次出现区间为 lil_ilirir_iri ,则闭区间 [li,ri][l_i, r_i][li,ri] 就是以 xxx 为根的子树的 DFS 序;

则可以通过 DFS 序将子树的统计转化为序列上的区间统计;

3. 性质

树上任意两点 x,yx, yx,y 路径上的点为,最后一个 xxx 到第一个 yyy 之间出现奇数次的数,再加上两点的 LCA;

说明

由于在 DFS 序中节点 xxx 第一次出现的位置到最后一次出现的位置之间都是 xxx 子树上的节点;

所以在 xxx 节点最后一次出现到 yyy 节点第一次出现间的节点即为 xxxyyy 的祖先;

但是,由于在这其中可能会遍历到其他不在两点路径上的子树,则这些字数上的节点均应是已经回溯的,则出现次数为 2 次,所以找这段区间中出现次数为奇数的节点,为两点上的路径;

由于在 DFS 序中,两点的遍历顺序为 x→LCA(x,y)→yx \rarr LCA(x, y) \rarr yxLCA(x,y)y ,但是又由于 DFS 遍历时,只有进入节点与完全遍历完子树时才会记录,所以还要加上两点的 LCA;

4. DFN 序

DFN 序则为,在 DFN 序中该节点被搜索的次序 (时间戳) ;

void dfs(int i) {
    dfn[i] = ++len;
    flag[i] = true;
    for (int t = 0; t < g[i].size(); t++) {
        int v = g[i][t];
        if (!flag[v]) {
            dfs(v);
        }
    }
    return;
}

二、欧拉序

1. 定义

进入节点时记录,每次遍历完一个子节点时,返回到此节点记录,得到的 2∗N−12 * N - 12N1 长的序列;

void dfs(int i) {
    d[++len] = i;
    flag[i] = true;
    for (int t = 0; t < g[i].size(); t++) {
        int v = g[i][t];
        if (!flag[v]) {
            dfs(v);
            d[++len] = i;
        }
    }
    return;
}

2. 性质

  1. 节点 xxx 第一次出现与最后一次出现的位置之间的节点均为 xxx 的子节点;

  2. 任意两个节点的 LCA 。是欧拉序中两节点第一次出现位置中深度最小的节点;

    说明

    因为在欧拉序中节点 xxx 第一次出现的位置到最后一次出现的位置之间都是 xxx 子树上的节点;

    所以在 xxx 节点最后一次出现到 yyy 节点第一次出现间的节点即为 xxxyyy 的祖先;

    但因为 xxx 可能为 yyy 的祖先,或 yyy 可能为 xxx 的祖先;

    所以应查找 xxxyyy 第一次出现的区间内的节点;

    则可将 xxxyyy 看作以其 LCA 为根的子树上的两个节点,则在欧拉序遍历时,顺序为 x→LCA(x,y)→yx \rarr LCA(x, y) \rarr yxLCA(x,y)y ,则区间中深度最小的节点即为两点的 LCA ;

    用 RMQ 计算 xxxyyy 第一次出现的区间内深度最小的节点即可;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值