dfs序(基础讲解)

dfs序简介

dfs序一般用于树状结构中,如图:
在这里插入图片描述

图中红色序号为每个点对应的dfs序序号,黑色序号为每个点默认的序号,我称之为节点序序号(下文同)
可见,dfs序如其名,dfs序序号是按照dfs顺序标记的,所以说给每个节点安排上dfs序序号也很简单,只要dfs的时候顺便标上就行了,dfs第多少次就给dfs到的点标为多少。

代码模板

代码如下:

//vector<int> node[N];
//int in[N],out[N];
//int Time = 0; //时间戳
void dfs(int now,int fa){
 	in[now]=++Time;
 	for(int i=0;i<node[now].size();i++)
  		if(node[now][i]!=fa) dfs(node[now][i],now);
 	out[now]=Time;
}

数组讲解:
node[i] 表示二维数组,这个应该会吧,不会的话可以看看STL讲解,也可以私聊我。
in[i] 表示节点序序号为i的节点为根节点的树的开头,同时也是节点序序号为i的节点对应的dfs序序号。
out[i] 表示节点序序号为i的节点为根节点的树的结尾,必定是个树叶对应的dfs序序号。
以上面的图为例:
在这里插入图片描述

节点序序号为1的节点为根节点所对应的子树为绿框所选部分,其对应的树为dfs序序号4~8,因此,in[1] = 4 , out[1] = 8;
节点序序号为8的节点为根节点所对应的子树为蓝框所选部分,其对应的树为dfs序序号2~3,因此,in[8] = 2 , out[8] = 3;
节点序序号为6的节点为根节点所对应的子树为其本身(图中未标),其对应的树为dfs序序号7~7,因此,in[6] = 7 , out[6] = 7。
变量讲解:
now 代表dfs到达的当前节点;
fa 代表father,当前节点的父亲节点,主要用于循环体内部的判断;
Time 代表时间戳,什么时间戳扯这么高大上干什么? ,记录dfs的次数,dfs一次Time自加一次,其实Time记录的就是dfs序序号,用于给in数组和out数组赋值,in数组和out数组存储的就是节点的dfs序序号。
代码讲解:
说白了就是dfs板子加了几句:
dfs板子:

void dfs(int now,int fa){
  for(int i=0;i<node[now].size();i++)
    if(node[now][i]!=fa) dfs(node[now][i],now);
}

这不就是深度优先搜索嘛,只不过在每次进入dfs的时候给in数组赋上值,因为开始dfs代表着进入这棵子树了;每次dfs结束return回去的时候再给out数组赋上值,因为return回去代表子树上的节点全部访问完毕,此时Time就是出树的dfs序序号。赋值赋的就是dfs序序号。
本质讲解:
整理一下,
代码实现上,很简单,dfs加上两个赋值语句;
目的上,我们dfs的目的是对in数组和out数组进行赋值,对它们进行赋值的目的是实现节点序序号转化成dfs序序号,而为什么要将节点序序号转化成dfs序序号,就要谈谈dfs序的优势了!

dfs序的优势及用途

dfs序的主要作用就是将一个子树变成序列上的一个连续区间。
还是以上图为例,
在这里插入图片描述

绿色子树可以通过dfs序序号表示出来,4~8;
红色子树表示为2~3;
显然,可以用一连续区间表示出来任意子树。
这样的变换可以解决类似“修改树上某点,输出子树和或者最大值最小值”等问题。
常常配合线段树或树状数组。
树状数组讲解

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不牌不改

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值