对比以下两种写法:
(一)
void dfs(int u) {
path.push_back(u);
while (!E[u].empty()) {
auto v = E[u].back();
E[u].pop_back();
dfs(v);
}
}
for (auto& u : path) printf("%d ", u);
(二)
void dfs(int u) {
while (!E[u].empty()) {
auto v = E[u].back();
E[u].pop_back();
dfs(v);
}
path.push_back(u);
}
reverse(path.begin(), path.end());
for (auto& u : path) printf("%d ", u);
先给 Hack 数据:
3 4
1 2
2 1
2 3
3 2
第一种的代码跑出来是 1 2 1 3 2,显然是错误的。
分析 DFS 的过程:
dfs(1): 包含边 2
dfs(2): 包含边 1 3
dfs(1): 没有边
end
dfs(3): 包含边 2
dfs(2): 没有边
end
end
end
end
问题在于「没有边」。
如果没有边,说明这个点已经遍历完毕,应该在路径的末尾输出,但 DFS 时会先进入这个点,告知程序这个点是路径末端的。但如果采用第一种代码的写法,这个点会直接计入路径并输出,这并不是我们想要的结果。
因此,路径末端的点会首先被找到,最先结束递归,并入栈,表明在结束 DFS 时入栈就是正确的。