( 数据结构专题 )【 dfs序 】

( 数据结构专题 )【 dfs序 】

Dfs序是一棵树从根节点出发,dfs遍历时依次经过的节点序列。

作用:对于只对某个节点的 子树 进行操作时,可以将树简化为一维序列。

 

 

上面这个树的遍历顺序是:1 4 9 8 13 12 3 7 6 11 10 14 2 5

性质:对于一棵树的dfs序而言,同一棵子树所对应的点一定是dfs序中连续的一段。

这个性质非常重要,在利用dfs序来解题的过程中,这个不可缺少!

证明:在dfs遍历时,当进入一个节点之后,dfs会先把当前的节点的所有子节点都遍历一遍,然后在回溯到当前节点,在这个过程中,它的所有子孙节点一定都被访问过了,而且在这之前,它的任何一个子孙节点都不可能被访问过。然后它才离开当前子树,回到父亲节点,再访问其他子树,所以同一子树的节点在dfs序中一定是连续的一段。

 

实现

dfs,顺便记录下访问的顺序。设 dfn[u] = ++tim 为u是第 tim 个访问的节点。

那么怎么获取当前节点在dfs序中的范围呢?

我们引入sz[u] 表示u子树的节点数。

那么对于u节点,他的所有子节点的范围就是 [ dfn[u], dfn[u] + sz[u] - 1 ]

为了方便我们还可以引入rev[u] ,原节点编号的转换

 

代码:

#include <bits/stdc++.h>

using namespace std;

const int maxn = 2e5+10;
struct node {
    int to,nxt,w;
}e[maxn];
int dfn[maxn],sz[maxn],tim,rev[maxn];
int head[maxn],cnt,n;

void addage( int u, int v )
{
    e[cnt].to = v;
    e[cnt].nxt = head[u];
    head[u] = cnt++;
}

void dfs( int u, int f )
{
    dfn[u] = ++tim;
    rev[tim] = u;
    sz[u] = 1;
    for ( int i=head[u]; i!=-1; i=e[i].nxt ) {
        int v = e[i].to;
        if ( v==f ) continue;
        dfs(v,u);
        sz[u] += sz[v];
    }
}

int main()
{
    memset(head,-1,sizeof(head));cnt=0;
    cin>>n;
    for ( int i=0; i<n-1; i++ ) {
        int u,v;scanf("%d %d",&u,&v);
        addage(u,v);addage(v,u);
    }
    dfs(1,1);
    
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值