<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=46.242.14.123&amp;*</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=46.242.14.123&amp;*"/>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/46.242.14.123"/>
		<updated>2026-04-18T06:11:21Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%85%D0%BE%D0%B4_%D0%B2_%D0%B3%D0%BB%D1%83%D0%B1%D0%B8%D0%BD%D1%83,_%D1%86%D0%B2%D0%B5%D1%82%D0%B0_%D0%B2%D0%B5%D1%80%D1%88%D0%B8%D0%BD&amp;diff=66086</id>
		<title>Обход в глубину, цвета вершин</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9E%D0%B1%D1%85%D0%BE%D0%B4_%D0%B2_%D0%B3%D0%BB%D1%83%D0%B1%D0%B8%D0%BD%D1%83,_%D1%86%D0%B2%D0%B5%D1%82%D0%B0_%D0%B2%D0%B5%D1%80%D1%88%D0%B8%D0%BD&amp;diff=66086"/>
				<updated>2018-06-19T18:45:38Z</updated>
		
		<summary type="html">&lt;p&gt;46.242.14.123: /* Реализация */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Обход в глубину''' (поиск в глубину, англ. ''Depth-First Search'', ''DFS'') — один из основных методов обхода [[Основные определения теории графов|графа]], часто используемый для [[Использование обхода в глубину для проверки связности|проверки связности]], поиска [[Использование обхода в глубину для поиска цикла в ориентированном графе|цикла]] и [[Использование обхода в глубину для поиска компонент сильной связности|компонент сильной связности]] и для [[Использование обхода в глубину для топологической сортировки|топологической сортировки]].&lt;br /&gt;
&lt;br /&gt;
== Алгоритм ==&lt;br /&gt;
&lt;br /&gt;
=== Общая идея ===&lt;br /&gt;
Общая идея алгоритма состоит в следующем:  для каждой ''не пройденной'' [[Основные определения теории графов|вершины]] необходимо найти все ''не пройденные'' [[Основные определения теории графов|смежные вершины]] и повторить поиск для них.&lt;br /&gt;
&lt;br /&gt;
=== Пошаговое представление ===&lt;br /&gt;
#Выбираем  любую вершину из еще ''не пройденных'', обозначим ее как &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;.&lt;br /&gt;
#Запускаем процедуру &amp;lt;tex&amp;gt;\mathrm{dfs(u)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
#*Помечаем вершину &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; как ''пройденную''&lt;br /&gt;
#*Для каждой ''не пройденной'' смежной с &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; вершиной (назовем ее &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt;) запускаем &amp;lt;tex&amp;gt;\mathrm{dfs(v)}&amp;lt;/tex&amp;gt;&lt;br /&gt;
#Повторяем шаги 1 и 2, пока все вершины не окажутся ''пройденными''.&lt;br /&gt;
&lt;br /&gt;
=== Реализация ===&lt;br /&gt;
В массиве &amp;lt;tex&amp;gt;\mathrm{visited[]}&amp;lt;/tex&amp;gt; хранится информация о ''пройденных'' и ''не пройденных'' вершинах.&lt;br /&gt;
&lt;br /&gt;
 '''function''' doDfs(G[n]: '''Graph'''):&amp;lt;font color=darkgreen&amp;gt; // функция принимает граф G с количеством вершин n и выполняет обход в глубину во всем графе &amp;lt;/font&amp;gt;&lt;br /&gt;
    visited = array[n, ''false''] &amp;lt;font color=darkgreen&amp;gt; // создаём массив посещённых вершины длины n, заполненный ''false'' изначально&amp;lt;/font&amp;gt;&lt;br /&gt;
           &lt;br /&gt;
    '''function''' dfs(u: '''int'''):   &lt;br /&gt;
       visited[u] = ''true''&lt;br /&gt;
       '''for''' v: (u, v) '''in''' G        &lt;br /&gt;
          '''if''' '''not''' visited[v]               &lt;br /&gt;
             dfs(v)&lt;br /&gt;
 &lt;br /&gt;
    '''for''' i = 1 '''to''' n             &lt;br /&gt;
       '''if''' '''not''' visited[i]                    &lt;br /&gt;
          dfs(i)&lt;br /&gt;
&lt;br /&gt;
=== Время работы ===&lt;br /&gt;
Оценим время работы обхода в глубину. Процедура &amp;lt;tex&amp;gt;\mathrm{dfs}&amp;lt;/tex&amp;gt; вызывается от каждой вершины не более одного раза, а внутри процедуры рассматриваются все такие [[Основные определения теории графов|ребра]] &amp;lt;tex&amp;gt;\{e\ |\ \mathrm{begin(e)} = u\}&amp;lt;/tex&amp;gt;. Всего таких ребер для всех вершин в графе &amp;lt;tex&amp;gt;O(E)&amp;lt;/tex&amp;gt;, следовательно, время работы алгоритма оценивается как &amp;lt;tex&amp;gt;O(V+E)&amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Цвета вершин ==&lt;br /&gt;
Зачастую, простой информации &amp;quot;были/не были в вершине&amp;quot; не хватает для конкретных целей.&lt;br /&gt;
&lt;br /&gt;
Поэтому в процессе алгоритма вершинам задают некоторые цвета:&lt;br /&gt;
&lt;br /&gt;
*если вершина ''белая'', значит, мы в ней еще не были, вершина ''не пройдена'';&lt;br /&gt;
*''серая'' — вершина ''проходится'' в текущей процедуре &amp;lt;tex&amp;gt;\mathrm{dfs}&amp;lt;/tex&amp;gt;;&lt;br /&gt;
*''черная'' — вершина ''пройдена'', все итерации &amp;lt;tex&amp;gt;\mathrm{dfs}&amp;lt;/tex&amp;gt; от нее завершены.&lt;br /&gt;
&lt;br /&gt;
Такие &amp;quot;метки&amp;quot; в основном используются при [[Использование обхода в глубину для поиска цикла в ориентированном графе|поиске цикла]].&lt;br /&gt;
&lt;br /&gt;
=== Реализация ===&lt;br /&gt;
Отличие реализации с цветами от предыдущей лишь в массиве &amp;lt;tex&amp;gt;\mathrm{visited[]}&amp;lt;/tex&amp;gt;, который мы назовем теперь &amp;lt;tex&amp;gt;\mathrm{color[]}&amp;lt;/tex&amp;gt;. В нем будет хранится информация о цветах вершин.&lt;br /&gt;
&lt;br /&gt;
 '''function''' doDfs(G[n]: '''Graph'''):&amp;lt;font color=darkgreen&amp;gt; // функция принимает граф G с количеством вершин n и выполняет обход в глубину во всем графе &amp;lt;/font&amp;gt;&lt;br /&gt;
    color = array[n, ''white'']&lt;br /&gt;
                    &lt;br /&gt;
    '''function''' dfs(u: '''int'''):&lt;br /&gt;
       color[u] = ''gray''           &lt;br /&gt;
       '''for''' v: (u, v) '''in''' G                   &lt;br /&gt;
          '''if''' color[v] == ''white''&lt;br /&gt;
             dfs(v)&lt;br /&gt;
       color[u] = ''black''   &lt;br /&gt;
                    	   &lt;br /&gt;
    '''for''' i = 1 '''to''' n             &lt;br /&gt;
       '''if''' color[i] == ''white''                &lt;br /&gt;
          dfs(i)&lt;br /&gt;
&lt;br /&gt;
=== Пример ===&lt;br /&gt;
Рассмотрим, как будут изменяться цвета вершин при обходе в глубину данного графа.&lt;br /&gt;
&lt;br /&gt;
{| style=&amp;quot;background-color:#CCC;margin:0.5px;width:600px&amp;quot;&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Описание шага&lt;br /&gt;
!style=&amp;quot;background-color:#EEE&amp;quot;| Состояние графа&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| В функции &amp;lt;tex&amp;gt;\mathrm{doDfs}&amp;lt;/tex&amp;gt; присваиваем всем вершинам в массиве &amp;lt;tex&amp;gt;\mathrm{color[]}&amp;lt;/tex&amp;gt; белый цвет. Затем проверяем, что первая вершина окрашена в белый цвет. Заходим в нее и раскрашиваем ее в серый цвет.&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| [[Файл:dfs1.png‎|150px|]]&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| Пробуем пойти в вершину с номером 2. Проверяем, что она белая, и переходим в нее. Окрашиваем ее в серый цвет.&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| [[Файл:dfs2.png‎|150px|]]&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| Пробуем пойти в вершину с номером 3. Проверяем, что она белая, и переходим в нее. Окрашиваем ее в серый цвет.&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| [[Файл:dfs3.png‎|150px|]]&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| Проверяем, что из вершины с номером 3 не исходит ни одного ребра. Помечаем ее в черный цвет и возвращаемся в вершину с номером 2.&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| [[Файл:dfs4.png‎|150px|]]&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| Пробуем пойти в вершину с номером 4. Проверяем, что она белая, и переходим в нее. Окрашиваем ее в серый цвет.&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| [[Файл:dfs5_6_7.png‎|150px|]]&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| Пробуем пойти в вершину с номером 3. Видим, что она черного цвета, и остаемся на месте.&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| [[Файл:dfs5_6_7.png‎|150px|]]&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| Пробуем пойти в вершину с номером 1. Видим, что она серого цвета, и остаемся на месте.&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| [[Файл:dfs5_6_7.png‎|150px|]]&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| Из вершины с номером 4 больше нет исходящих ребер. Помечаем ее в черный цвет и возвращаемся в вершину с номером 2.&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| [[Файл:dfs8.png‎|150px|]]&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| Из вершины с номером 2 больше нет исходящих ребер. Помечаем ее в черный цвет и возвращаемся в вершину с номером 1.&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| [[Файл:dfs9.png‎|150px|]]&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| Из вершины с номером 1 больше нет исходящих ребер. Помечаем ее в черный цвет и выходим в программу &amp;lt;tex&amp;gt;\mathrm{doDfs}&amp;lt;/tex&amp;gt;. В ней проверяем, что все вершины окрашены в черный цвет. Выходим из функции &amp;lt;tex&amp;gt;\mathrm{doDfs}&amp;lt;/tex&amp;gt;. Алгоритм завершен.&lt;br /&gt;
|style=&amp;quot;background-color:#FFF;padding:2px 10px&amp;quot;| [[Файл:dfs10.png‎|150px|]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Дерево обхода в глубину ==&lt;br /&gt;
[[Image: Colors.png|thumb|240px|Типы ребер, определяемые деревом обхода:&amp;lt;br&amp;gt;&lt;br /&gt;
1) ребра дерева&amp;lt;br&amp;gt;&lt;br /&gt;
2) &amp;lt;font color=#3771c8&amp;gt;обратные&amp;lt;/font&amp;gt; ребра&amp;lt;br&amp;gt;&lt;br /&gt;
3) &amp;lt;font color=#71c837&amp;gt;прямые&amp;lt;/font&amp;gt; ребра&amp;lt;br&amp;gt;&lt;br /&gt;
4) &amp;lt;font color=#ff2a2a&amp;gt;перекрестные&amp;lt;/font&amp;gt; ребра]]&lt;br /&gt;
&lt;br /&gt;
Рассмотрим подграф предшествования обхода в глубину &amp;lt;tex&amp;gt;G_p = (V, E_p)&amp;lt;/tex&amp;gt;, где &amp;lt;tex&amp;gt;E_p = \{(p[u], u) : u \in V,\ p[u] \neq NIL\}&amp;lt;/tex&amp;gt;, где в свою очередь &amp;lt;tex&amp;gt;p[u]&amp;lt;/tex&amp;gt; — вершина, от которой был вызван &amp;lt;tex&amp;gt;\mathrm{dfs(u)}\ &amp;lt;/tex&amp;gt; (для вершин, от которых &amp;lt;tex&amp;gt;\mathrm{dfs}&amp;lt;/tex&amp;gt; был вызван нерекурсивно это значение соответственно равно &amp;lt;tex&amp;gt;NIL&amp;lt;/tex&amp;gt;). Подграф предшествования поиска в глубину образует ''лес обхода в глубину'', который состоит из нескольких ''деревьев обхода в глубину''. С помощью полученного леса можно классифицировать ребра графа &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt;:&lt;br /&gt;
* ''Ребрами дерева'' назовем те ребра из &amp;lt;tex&amp;gt;G&amp;lt;/tex&amp;gt;, которые вошли в &amp;lt;tex&amp;gt;G_p&amp;lt;/tex&amp;gt;. &lt;br /&gt;
* Ребра &amp;lt;tex&amp;gt;(u, v)&amp;lt;/tex&amp;gt;, соединяющие вершину &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; с её предком &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; в дереве обхода в глубину назовем ''обратными ребрами'' (для неориентированного графа предок должен быть ''не родителем'', так как иначе ребро будет являться ребром дерева). &lt;br /&gt;
* Ребра &amp;lt;tex&amp;gt;(u, v)&amp;lt;/tex&amp;gt;, не являющиеся ребрами дерева и соединяющие вершину &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt; с её потомком &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; в дереве обхода в глубину назовем ''прямыми ребрами'' (в неориентированном графе нет разницы между прямыми и обратными ребрами, поэтому все такие ребра считаются обратными). &lt;br /&gt;
* Все остальные ребра назовем ''перекрестными ребрами'' — такие ребра могут соединять вершины одного и того же дерева обхода в глубину, когда ни одна из вершин не является предком другой, или соединять вершины в разных деревьях.&lt;br /&gt;
Алгоритм &amp;lt;tex&amp;gt;\mathrm{dfs}&amp;lt;/tex&amp;gt; можно модифицировать так, что он будет классифицировать встречающиеся при работе ребра. Ключевая идея состоит в том, что каждое ребро &amp;lt;tex&amp;gt;(u, v)&amp;lt;/tex&amp;gt; можно классифицировать при помощи цвета вершины &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; при первом его исследовании, а именно:&lt;br /&gt;
* Белый цвет вершины &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; по определению &amp;lt;tex&amp;gt;\mathrm{dfs}&amp;lt;/tex&amp;gt; говорит о том, что это ''ребро дерева''.&lt;br /&gt;
* Серый цвет в силу того, что серые вершины всегда образуют нисходящий путь в каком-либо из деревьев &amp;lt;tex&amp;gt;\mathrm{dfs}&amp;lt;/tex&amp;gt; и встреченная вершина &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; лежит на нем выше вершины &amp;lt;tex&amp;gt;u&amp;lt;/tex&amp;gt;, определяет ''обратное ребро'' (для неориентированного графа необходимо проверить условие &amp;lt;tex&amp;gt;v \neq p[u]&amp;lt;/tex&amp;gt;).&lt;br /&gt;
* Черный цвет, соответственно, указывает на ''прямое'' или ''перекрестное ребро''.&lt;br /&gt;
&lt;br /&gt;
== См. также ==&lt;br /&gt;
* [[Обход в ширину]]&lt;br /&gt;
&lt;br /&gt;
== Источники информации ==&lt;br /&gt;
*[http://ru.wikipedia.org/wiki/Поиск_в_глубину Википедия {{---}} Поиск в глубину]&lt;br /&gt;
*[http://en.wikipedia.org/wiki/Depth-first_search Wikipedia {{---}} Depth-first search]&lt;br /&gt;
*[http://www.e-maxx.ru/algo/dfs Обход в глубину. Реализации.]&lt;br /&gt;
* Томас Кормен, Чарльз Лейзерсон, Рональд Ривест, Клиффорд Штайн. Алгоритмы: построение и анализ, второе издание. Пер. с англ. — Издательский дом &amp;quot;Вильямс&amp;quot;, 2007. — 1296 с. — Глава 22. Элементарные алгоритмы для работы с графами.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Обход в глубину]]&lt;/div&gt;</summary>
		<author><name>46.242.14.123</name></author>	</entry>

	</feed>