<?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=5.44.168.243&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=5.44.168.243&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/5.44.168.243"/>
		<updated>2026-04-13T03:25:47Z</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_%D1%88%D0%B8%D1%80%D0%B8%D0%BD%D1%83&amp;diff=75086</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_%D1%88%D0%B8%D1%80%D0%B8%D0%BD%D1%83&amp;diff=75086"/>
				<updated>2020-10-08T13:08:24Z</updated>
		
		<summary type="html">&lt;p&gt;5.44.168.243: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Обход в ширину''' (Поиск в ширину, англ. ''BFS'', ''Breadth-first search'') — один из простейших алгоритмов обхода [[Основные определения теории графов|графа]], являющийся основой для многих важных алгоритмов для работы с графами.&lt;br /&gt;
&lt;br /&gt;
== Описание алгоритма ==&lt;br /&gt;
[[Image: Graph-BFS.gif|thumb|240px|Алгоритм BFS&amp;lt;br&amp;gt;&lt;br /&gt;
&amp;lt;font color=#3c9eff&amp;gt;посещенные&amp;lt;/font&amp;gt; вершины&amp;lt;br&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Пусть задан невзвешенный ориентированный граф &amp;lt;tex&amp;gt; G = (V, E) &amp;lt;/tex&amp;gt;, в котором выделена исходная вершина &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt;. Требуется найти длину кратчайшего пути (если таковой имеется) от одной заданной вершины до другой. Частным случаем указанного графа является невзвешенный неориентированный граф, т.е. граф, в котором для каждого ребра найдется обратное, соединяющее те же вершины в другом направлении.&lt;br /&gt;
&lt;br /&gt;
Для алгоритма нам потребуются [[Очередь|очередь]] и множество посещенных вершин &amp;lt;tex&amp;gt; was &amp;lt;/tex&amp;gt;, которые изначально содержат одну вершину &amp;lt;tex&amp;gt; s &amp;lt;/tex&amp;gt;. На каждом шагу алгоритм берет из начала очереди вершину &amp;lt;tex&amp;gt; v &amp;lt;/tex&amp;gt; и добавляет все непосещенные смежные с &amp;lt;tex&amp;gt; v &amp;lt;/tex&amp;gt; вершины в &amp;lt;tex&amp;gt; was &amp;lt;/tex&amp;gt; и в конец очереди. Если очередь пуста, то алгоритм завершает работу.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Анализ времени работы ==&lt;br /&gt;
Оценим время работы для входного графа &amp;lt;tex&amp;gt;G = (V, E)&amp;lt;/tex&amp;gt;, где множество ребер &amp;lt;tex&amp;gt; E &amp;lt;/tex&amp;gt; представлено списком смежности. В очередь добавляются только непосещенные вершины, поэтому каждая вершина посещается не более одного раза. Операции внесения в очередь и удаления из нее требуют &amp;lt;tex&amp;gt; O(1) &amp;lt;/tex&amp;gt; времени, так что общее время работы с очередью составляет &amp;lt;tex&amp;gt; O(|V|) &amp;lt;/tex&amp;gt; операций. Для каждой вершины &amp;lt;tex&amp;gt; v &amp;lt;/tex&amp;gt; рассматривается не более &amp;lt;tex&amp;gt; \mathrm{deg}(v) &amp;lt;/tex&amp;gt; ребер, инцидентных ей. Так как &amp;lt;tex&amp;gt; \sum\limits_{v \in V} \mathrm{deg}(v) = 2|E| &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;
&lt;br /&gt;
{{Утверждение&lt;br /&gt;
|statement=&lt;br /&gt;
В очереди поиска в ширину расстояние вершин до &amp;lt;tex&amp;gt;s&amp;lt;/tex&amp;gt; монотонно неубывает.&lt;br /&gt;
|proof=&lt;br /&gt;
Докажем это утверждение индукцией по числу выполненных алгоритмом шагов.&lt;br /&gt;
&lt;br /&gt;
Введем дополнительный инвариант: у любых двух вершин из очереди, расстояние до &amp;lt;tex&amp;gt; s &amp;lt;/tex&amp;gt; отличается не более чем на &amp;lt;tex&amp;gt; 1 &amp;lt;/tex&amp;gt;.  &lt;br /&gt;
&lt;br /&gt;
'''База''': изначально очередь содержит только одну вершину &amp;lt;tex&amp;gt; s &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
'''Переход''': пусть после &amp;lt;tex&amp;gt; i-й &amp;lt;/tex&amp;gt; итерации в очереди &amp;lt;tex&amp;gt; a + 1 &amp;lt;/tex&amp;gt; вершин с расстоянием &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; b &amp;lt;/tex&amp;gt; вершин с расстоянием &amp;lt;tex&amp;gt; x + 1 &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Рассмотрим &amp;lt;tex&amp;gt; i-ю &amp;lt;/tex&amp;gt; итерацию. Из очереди достаем вершину &amp;lt;tex&amp;gt; v &amp;lt;/tex&amp;gt;, с расстоянием &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt;. Пусть у &amp;lt;tex&amp;gt;v&amp;lt;/tex&amp;gt; есть &amp;lt;tex&amp;gt;r  &amp;lt;/tex&amp;gt; непосещенных смежных вершин. Тогда, после их добавления, в очереди находится &amp;lt;tex&amp;gt; a &amp;lt;/tex&amp;gt; вершин с расстоянием &amp;lt;tex&amp;gt; x &amp;lt;/tex&amp;gt; и, после них, &amp;lt;tex&amp;gt; b + r &amp;lt;/tex&amp;gt; вершин с расстоянием &amp;lt;tex&amp;gt; x + 1 &amp;lt;/tex&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Оба инварианта сохранились, &amp;lt;tex&amp;gt;  \Rightarrow &amp;lt;/tex&amp;gt; после любого шага алгоритма элементы в очереди неубывают. &lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{Теорема&lt;br /&gt;
|statement=&lt;br /&gt;
Алгоритм поиска в ширину в невзвешенном графе находит длины кратчайших путей до всех достижимых вершин.&lt;br /&gt;
|proof=&lt;br /&gt;
Допустим, что это не так. Выберем из вершин, для которых кратчайшие пути от &amp;lt;tex&amp;gt; s &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;, а предок в кратчайшем пути до &amp;lt;tex&amp;gt; u &amp;lt;/tex&amp;gt; — вершина &amp;lt;tex&amp;gt; w &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Так как &amp;lt;tex&amp;gt; w &amp;lt;/tex&amp;gt; — предок &amp;lt;tex&amp;gt; u &amp;lt;/tex&amp;gt; в кратчайшем пути, то &amp;lt;tex&amp;gt; \rho(s, u) = \rho(s, w) + 1 &amp;gt; \rho(s, w) &amp;lt;/tex&amp;gt;, и расстояние до &amp;lt;tex&amp;gt; w &amp;lt;/tex&amp;gt; найдено верно, &amp;lt;tex&amp;gt; \rho(s, w) = d[w] &amp;lt;/tex&amp;gt;. Значит, &amp;lt;tex&amp;gt; \rho(s, u) = d[w] + 1 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&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; d[u] = d[v] + 1 &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Расстояние до &amp;lt;tex&amp;gt; u &amp;lt;/tex&amp;gt; найдено некорректно, поэтому &amp;lt;tex&amp;gt; \rho(s, u) &amp;lt; d[u] &amp;lt;/tex&amp;gt;. Подставляя сюда два последних равенства, получаем &amp;lt;tex&amp;gt; d[w] + 1 &amp;lt; d[v] + 1 &amp;lt;/tex&amp;gt;, то есть, &amp;lt;tex&amp;gt; d[w] &amp;lt; d[v] &amp;lt;/tex&amp;gt;. Из ранее доказанной леммы следует, что в этом случае вершина &amp;lt;tex&amp;gt; w &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 &amp;lt;/tex&amp;gt; не может быть предком &amp;lt;tex&amp;gt; u &amp;lt;/tex&amp;gt; в дереве обхода в ширину, мы пришли к противоречию, следовательно, найденные расстояния до всех вершин являются кратчайшими.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Дерево обхода в ширину == &lt;br /&gt;
&lt;br /&gt;
Поиск в ширину также может построить [[Дерево, эквивалентные определения|дерево]] поиска в ширину. Изначально оно состоит из одного корня &amp;lt;tex&amp;gt; s &amp;lt;/tex&amp;gt;. Когда мы добавляем непосещенную вершину в очередь, то добавляем ее и ребро, по которому мы до нее дошли, в дерево. Поскольку каждая вершина может быть посещена не более одного раза, она имеет не более одного родителя. После окончания работы алгоритма для каждой достижимой из &amp;lt;tex&amp;gt; s &amp;lt;/tex&amp;gt; вершины &amp;lt;tex&amp;gt; t &amp;lt;/tex&amp;gt; путь в дереве поиска в ширину соответствует кратчайшему пути от &amp;lt;tex&amp;gt; s &amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt; t &amp;lt;/tex&amp;gt; в &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Реализация ==&lt;br /&gt;
&lt;br /&gt;
Предложенная ниже функция возвращает кратчайшее расстояние между двумя вершинами.&lt;br /&gt;
*&amp;lt;tex&amp;gt; \mathtt{source} &amp;lt;/tex&amp;gt; — исходная вершина&lt;br /&gt;
*&amp;lt;tex&amp;gt; \mathtt{destination} &amp;lt;/tex&amp;gt; — конечная вершина&lt;br /&gt;
*&amp;lt;tex&amp;gt; \mathtt{G} &amp;lt;/tex&amp;gt; — граф, состоящий из списка вершин &amp;lt;tex&amp;gt; \mathtt{V} &amp;lt;/tex&amp;gt; и списка смежности &amp;lt;tex&amp;gt; \mathtt{E} &amp;lt;/tex&amp;gt;. Вершины нумеруются целыми числами.&lt;br /&gt;
*&amp;lt;tex&amp;gt; \mathtt{Q} &amp;lt;/tex&amp;gt; — очередь.&lt;br /&gt;
*В поле &amp;lt;tex&amp;gt; \mathtt{d[u]} &amp;lt;/tex&amp;gt; хранится расстояние от &amp;lt;tex&amp;gt; \mathtt{source} &amp;lt;/tex&amp;gt; до &amp;lt;tex&amp;gt; \mathtt{u} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 '''int''' '''BFS'''(G: (V, E), source: '''int''', destination: '''int'''):&lt;br /&gt;
     d = '''int'''[|V|]&lt;br /&gt;
     '''fill'''(d, &amp;lt;tex&amp;gt; \infty &amp;lt;/tex&amp;gt;)&lt;br /&gt;
     d[source] = 0&lt;br /&gt;
     Q = &amp;lt;tex&amp;gt; \varnothing &amp;lt;/tex&amp;gt;&lt;br /&gt;
     Q.push(source)&lt;br /&gt;
     '''while''' Q &amp;lt;tex&amp;gt; \ne \varnothing &amp;lt;/tex&amp;gt; &lt;br /&gt;
         u = Q.pop()&lt;br /&gt;
         '''for''' v: (u, v) '''in''' E&lt;br /&gt;
             '''if''' d[v] == &amp;lt;tex&amp;gt; \infty &amp;lt;/tex&amp;gt;&lt;br /&gt;
                 d[v] = d[u] + 1&lt;br /&gt;
                 Q.push(v)&lt;br /&gt;
     '''return''' d[destination]&lt;br /&gt;
&lt;br /&gt;
Если требуется найти расстояние лишь между двумя вершинами, из функции можно выйти, как только будет установлено значение &amp;lt;tex&amp;gt; \mathtt{d[destination]} &amp;lt;/tex&amp;gt;.&lt;br /&gt;
Еще одна оптимизация может быть проведена при помощи метода [[Meet-in-the-middle#Задача о нахождении кратчайшего расстояния между двумя вершинами в графе|meet-in-the-middle]].&lt;br /&gt;
&lt;br /&gt;
== Вариации алгоритма ==&lt;br /&gt;
=== 0-1 BFS ===&lt;br /&gt;
Пусть в графе разрешены ребра веса &amp;lt;tex&amp;gt; 0 &amp;lt;/tex&amp;gt; и &amp;lt;tex&amp;gt; 1 &amp;lt;/tex&amp;gt;, необходимо найти кратчайший путь между двумя вершинами. Для решения данной задачи модифицируем приведенный выше алгоритм следующим образом: &lt;br /&gt;
&lt;br /&gt;
Вместо очереди будем использовать [[Персистентный_дек|дек]] (или можно даже steque). Если рассматриваемое ее ребро имеет вес &amp;lt;tex&amp;gt; 0 &amp;lt;/tex&amp;gt;, то будем добавлять вершину в начало, а иначе в конец. После этого добавления, дополнительный введенный инвариант в доказательстве [[#Корректность | расположения элементов в деке в порядке неубывания]] продолжает выполняться, поэтому порядок в деке сохраняется. И, соответственно, релаксируем расстояние до всех смежных вершин и, при успешной релаксации, добавляем их в дек. &lt;br /&gt;
&lt;br /&gt;
Таким образом, в начале дека всегда будет вершина, расстояние до которой меньше либо равно расстоянию до остальных вершин дека, и инвариант [[#Корректность | расположения элементов в деке в порядке неубывания]] сохраняется. Значит, алгоритм корректен на том же основании, что и обычный BFS. Очевидно, что каждая вершина войдет в дек не более двух раз, значит, асимптотика у данного алгоритма та же, что и у обычного BFS.&lt;br /&gt;
&lt;br /&gt;
=== 1-k BFS ===&lt;br /&gt;
Пусть в графе разрешены ребра целочисленного веса из отрезка &amp;lt;tex&amp;gt;1 \ldots k&amp;lt;/tex&amp;gt;, необходимо найти кратчайший путь между двумя вершинами. Представим ребро &amp;lt;tex&amp;gt;uv&amp;lt;/tex&amp;gt; веса &amp;lt;tex&amp;gt;m&amp;lt;/tex&amp;gt; как последовательность ребер &amp;lt;tex&amp;gt;uu_1u_2 \ldots u_{m - 1}v&amp;lt;/tex&amp;gt; (где &amp;lt;tex&amp;gt;u_1 \ldots u_{m - 1}&amp;lt;/tex&amp;gt; — новые вершины). Применим данную операцию ко всем ребрам графа &amp;lt;tex&amp;gt; G &amp;lt;/tex&amp;gt;. Получим граф, состоящий (в худшем случае) из &amp;lt;tex&amp;gt;k|E|&amp;lt;/tex&amp;gt; ребер и &amp;lt;tex&amp;gt;|V| + (k - 1)|E|&amp;lt;/tex&amp;gt; вершин. Для нахождения кратчайшего пути следует запустить BFS на новом графе. Данный алгоритм будет иметь асимптотику &amp;lt;tex&amp;gt; O(|V| + k|E|) &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;
== Источники информации ==&lt;br /&gt;
&lt;br /&gt;
* Томас Х. Кормен, Чарльз И. Лейзерсон, Рональд Л. Ривест, Клиффорд Штайн Алгоритмы: построение и анализ — 2-е изд. — М.: «Вильямс», 2007. — с. 459. — ISBN 5-8489-0857-4&lt;br /&gt;
* [http://e-maxx.ru/algo/bfs MAXimal :: algo :: Поиск в ширину]&lt;br /&gt;
* [[wikipedia:en:Breadth-first_search| Wikipedia {{---}} Breadth-first search]]&lt;br /&gt;
* [[wikipedia:ru:Поиск_в_ширину| Wikipedia {{---}} Поиск в ширину]]&lt;br /&gt;
* [http://rain.ifmo.ru/cat/view.php/vis/graph-general/bfs-2002 Визуализатор алгоритма]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Категория: Алгоритмы и структуры данных]]&lt;br /&gt;
[[Категория: Кратчайшие пути в графах]]&lt;/div&gt;</summary>
		<author><name>5.44.168.243</name></author>	</entry>

	</feed>