E025. Depth-first search
Источник: e-maxx.ru/algo, страница PDF 85.
Это один из основных Thuật toánов на đồ thịах. В результате поиска в глубину находится лексикоđồ thịически первый путь в đồ thịе. Thuật toán работает за O (N+M).
Applications Thuật toánа
● Поиск любого пути в đồ thịе.
● Поиск лексикоđồ thịически первого пути в đồ thịе.
● Проверка, является ли одна vertex дерева предком другой:
В начале и конце итерации поиска в глубину будет запоминать "время" захода и Đầu raа в каждой вершине. Теперь за O (1) можно find ответ: vertex i является предком вершины j тогда и только тогда, когда starti < startj и endi > endj.
● Bài toán LCA (Lowest common ancestor).
● Topological sorting:
Запускаем серию поисков в глубину, чтобы обойти все вершины đồ thịа. Отсортируем вершины по времени Đầu raа по убыванию - это и будет ответом.
● Проверка đồ thịа на ацикличность и нахождение цикла
● Поиск компонент сильной связности:
Сначала делаем топологическую сортировку, потом транспонируем đồ thị и проводим снова серию поисков в глубину в порядке, определяемом топологической сортировкой. Каждое cây поиска - сильносвязная компонента.
● Поиск мостов:
Сначала превращаем đồ thị в ориентированный, делая серию поисков в глубину, и ориентируя каждое edge так, как мы пытались по нему пройти. Затем находим сильносвязные компоненты. Мостами являются те рёбра, концы которых принадлежат разным сильносвязным компонентам.
Cài đặt
vector < vector<int> > g; // đồ thị
int n; // number вершин
vector<int> color; // цвет вершины (0, 1, или 2)
vector<int> time_in, time_out; // "времена" захода и Đầu raа из вершины
int dfs_timer = 0; // "таймер" для определения времён
void dfs (int v) {
time_in[v] = dfs_timer++;
color[v] = 1;
for (vector<int>::iterator i=g[v].begin(); i!=g[v].end(); ++i)
if (color[*i] == 0)
dfs (*i);
color[v] = 2;
time_out[v] = dfs_timer++;
} Это наиболее общий код. Во многих случаях времена захода и Đầu raа из вершины не важны, так же как и не важны цвета вершин (но тогда надо будет ввести аналогичный по смыслу булевский mảng used). Вот наиболее простая Cài đặt:
vector < vector<int> > g; // đồ thị
int n; // number вершин
vector<char> used;
void dfs (int v) {
used[v] = true;
for (vector<int>::iterator i=g[v].begin(); i!=g[v].end(); ++i)
if (!used[*i])
dfs (*i);
}
C# lời giải
bản nháp tự động, xem lại trước khi gửiusing System;
using System.Collections.Generic;
using System.Linq;
public static class AlgorithmDraft
{
// Auto-generated C# draft from the original e-maxx C/C++ listing. Review before production use.
vector < List<int> > g; // граф
int n; // число вершин
List<int> color; // цвет вершины (0, 1, или 2)
List<int> time_in, time_out; // "времена" захода и выхода из вершины
int dfs_timer = 0; // "таймер" для определения времён
void dfs (int v) {
time_in[v] = dfs_timer++;
color[v] = 1;
for (List<int>::iterator i=g[v].begin(); i!=g[v].end(); ++i)
if (color[*i] == 0)
dfs (*i);
color[v] = 2;
time_out[v] = dfs_timer++;
}
vector < List<int> > g; // граф
int n; // число вершин
List<char> used;
void dfs (int v) {
used[v] = true;
for (List<int>::iterator i=g[v].begin(); i!=g[v].end(); ++i)
if (!used[*i])
dfs (*i);
}
}
C++ lời giải
đã khớp/gốcvector < vector<int> > g; // граф
int n; // число вершин
vector<int> color; // цвет вершины (0, 1, или 2)
vector<int> time_in, time_out; // "времена" захода и выхода из вершины
int dfs_timer = 0; // "таймер" для определения времён
void dfs (int v) {
time_in[v] = dfs_timer++;
color[v] = 1;
for (vector<int>::iterator i=g[v].begin(); i!=g[v].end(); ++i)
if (color[*i] == 0)
dfs (*i);
color[v] = 2;
time_out[v] = dfs_timer++;
}
vector < vector<int> > g; // граф
int n; // число вершин
vector<char> used;
void dfs (int v) {
used[v] = true;
for (vector<int>::iterator i=g[v].begin(); i!=g[v].end(); ++i)
if (!used[*i])
dfs (*i);
}
Java lời giải
bản nháp tự động, xem lại trước khi gửiimport java.util.*;
import java.math.*;
public class AlgorithmDraft {
// Auto-generated Java draft from the original e-maxx C/C++ listing. Review before production use.
vector < ArrayList<Integer> > g; // граф
int n; // число вершин
ArrayList<Integer> color; // цвет вершины (0, 1, или 2)
ArrayList<Integer> time_in, time_out; // "времена" захода и выхода из вершины
int dfs_timer = 0; // "таймер" для определения времён
void dfs (int v) {
time_in[v] = dfs_timer++;
color[v] = 1;
for (ArrayList<Integer>::iterator i=g[v].begin(); i!=g[v].end(); ++i)
if (color[*i] == 0)
dfs (*i);
color[v] = 2;
time_out[v] = dfs_timer++;
}
vector < ArrayList<Integer> > g; // граф
int n; // число вершин
ArrayList<Character> used;
void dfs (int v) {
used[v] = true;
for (ArrayList<Integer>::iterator i=g[v].begin(); i!=g[v].end(); ++i)
if (!used[*i])
dfs (*i);
}
}
Материал разбит как Thuật toánическая Bài toán: изучить постановку, понять асимптотику и реализовать Thuật toán на выбранном языке.
Vacancies for this task
việc làm đang hoạt động with overlapping task tags are đã hiển thị.