d f s dfs dfs序是将树形结构转换为线性结构的一种方式。
dfs序
d
f
s
dfs
dfs序: 指每个节点在dfs深度优先遍历中的进出栈的时间序列。
定义三个数组:
i
n
n
[
x
]
inn[x]
inn[x]:表示结点
x
x
x入栈的时间戳。
o
u
t
t
[
x
]
outt[x]
outt[x]:表示结点
x
x
x出栈的时间戳,特殊的,出栈不算时间。
i
d
[
x
]
id[x]
id[x]:表示结点x在新的线性序列中的下标,
i
d
[
x
]
=
i
n
n
[
x
]
id[x]=inn[x]
id[x]=inn[x]。
下面,以下图为例进行具体说明:
假设
d
f
s
dfs
dfs访问顺序为:
A
,
B
,
E
,
F
,
K
,
C
,
G
,
H
,
I
A,B,E,F,K,C,G,H,I
A,B,E,F,K,C,G,H,I。
则结点的入栈出栈时间如下:
这样,我们得到一个新的线性序列:
A
,
B
,
E
,
F
,
K
,
C
,
G
,
H
,
I
A,B,E,F,K,C,G,H,I
A,B,E,F,K,C,G,H,I。
通过观察可以发现,以
x
x
x为根的子树在一个连续的区间,即在
x
x
x入栈和出栈之间,因此,如果要对子树进行操作,可以看作对一个区间进行操作,且这个区间对应新的线性序列中的
i
n
n
[
x
]
o
u
t
t
[
x
]
inn[x]~outt[x]
inn[x] outt[x]。
支持两种操作:
- 单个结点修改
对单个结点 x x x进行修改,则对应新的线性序列对 i d [ x ] id[x] id[x]进行修改。 - 对
x
x
x为根的子树进行修改
如对结点 B B B为根的子树进行操作,则对应线性序列区间 i n n [ B ] o u t t [ B ] inn[B]~outt[B] inn[B] outt[B],即区间 [ 2 , 5 ] [2,5] [2,5]进行操作。
【 d f s dfs dfs序列参考程序】
void dfs(int u)
{
inn[u]=++num; //入栈时间
s[u]=num; //新的线性序列
vis[u]=1;
for(int i=first[u];i!=-1;i=nex[i])
{
int v=to[i];
if(!vis[v]) dfs(v);
}
outt[u]=num; //出栈时间,不计算时间
}