Поиском в глубину (англ. depth-first search, DFS) или эйлеровым обходом называется рекурсивный алгоритм обхода корневого дерева или графа, начинающий в корневой вершине (в случае графа может быть выбрана произвольная вершина) и рекурсивно обходящий весь граф, посещая каждую вершину ровно один раз.
const int maxn = 1e5;
bool used[maxn]; // тут будем отмечать посещенные вершины
void dfs(int v) {
used[v] = true;
for (int u : g[v])
if (!used[u])
dfs(u);
}
Немного его модифицируем, а именно будем сохранять для каждой вершины, в какой момент мы в неё вошли и в какой вышли — соответствующие массивы будем называть и .
Как их заполнить: заведем таймер, отвечающий за «время» на текущем состоянии обхода, и будем инкрементировать его каждый раз, когда заходим в новую вершину:
int tin[maxn], tout[maxn];
int t = 0; // таймер
void dfs(int v) {
tin[v] = t++;
for (int u : g[v])
if (!used[u])
dfs(u);
tout[v] = t; // иногда счетчик тут тоже увеличивают
}
У этих массивов много полезных свойств:
- Вершина является предком . Эту проверку можно делать за константу.
- Два полуинтервала и либо не пересекаются, либо один вложен в другой.
- В массиве есть все числа от 0 до , причём у каждой вершины свой номер.
- Размер поддерева вершины (включая саму вершину) равен .
- Если ввести нумерацию вершин, соответствующую -ам, то индексы любого поддерева всегда будут каким-то промежутком в этой нумерации.
Как мы дальше увидим, эти свойства очень полезны в других обходах и самых разных задачах на деревья.