E025. Depth-first search

e-maxx algorithm original: C/C++ #algorithm #dfs #emaxx #graph #search
선택한 UI 언어에 맞게 문제 텍스트를 러시아어에서 번역합니다. 코드는 변경하지 않습니다.

Источник: e-maxx.ru/algo, страница PDF 85.

Это один из основных 알고리즘ов на 그래프ах. В результате поиска в глубину находится лексико그래프ически первый путь в 그래프е. 알고리즘 работает за O (N+M).

Applications 알고리즘а

● Поиск любого пути в 그래프е.

● Поиск лексико그래프ически первого пути в 그래프е.

● Проверка, является ли одна vertex дерева предком другой:

В начале и конце итерации поиска в глубину будет запоминать "время" захода и 출력а в каждой вершине. Теперь за O (1) можно find ответ: vertex i является предком вершины j тогда и только тогда, когда starti < startj и endi > endj.

● 문제 LCA (Lowest common ancestor).

● Topological sorting:

Запускаем серию поисков в глубину, чтобы обойти все вершины 그래프а. Отсортируем вершины по времени 출력а по убыванию - это и будет ответом.

● Проверка 그래프а на ацикличность и нахождение цикла

● Поиск компонент сильной связности:

Сначала делаем топологическую сортировку, потом транспонируем 그래프 и проводим снова серию поисков в глубину в порядке, определяемом топологической сортировкой. Каждое 트리 поиска - сильносвязная компонента.

● Поиск мостов:

Сначала превращаем 그래프 в ориентированный, делая серию поисков в глубину, и ориентируя каждое edge так, как мы пытались по нему пройти. Затем находим сильносвязные компоненты. Мостами являются те рёбра, концы которых принадлежат разным сильносвязным компонентам.

구현

vector < vector<int> > g; // 그래프

int n; // number вершин

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++;

} Это наиболее общий код. Во многих случаях времена захода и 출력а из вершины не важны, так же как и не важны цвета вершин (но тогда надо будет ввести аналогичный по смыслу булевский 배열 used). Вот наиболее простая 구현:

vector < vector<int> > g; // 그래프

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# 해법

자동 초안, 제출 전 검토
using 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++ 해법

매칭됨/원본
vector < 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 해법

자동 초안, 제출 전 검토
import 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);
    }
}

Материал разбит как 알고리즘ическая 문제: изучить постановку, понять асимптотику и реализовать 알고리즘 на выбранном языке.

Vacancies for this task

활성 채용 with overlapping task tags are 표시됨.

전체 채용
아직 활성 채용이 없습니다.