Изменения

Перейти к: навигация, поиск

Обход в ширину

11 567 байт добавлено, 19:35, 4 сентября 2022
м
rollbackEdits.php mass rollback
'''Поиск Обход в ширину''' (Поиск в ширину, англ. ''BFS'BFS', '', Breadth-first search'') — метод один из простейших алгоритмов обхода и разметки вершин [[Основные определения теории графов|графа]], являющийся основой для многих важных алгоритмов для работы с графами.
==Описание алгоритма ==[[Image: Graph-BFS.gif|thumb|240px|АлгоритмBFS<br><font color==#3c9eff>посещенные</font> вершины<br>]]
===Общая идея===
Поиск в ширину реализуется с помощью структуры очередь. Для этого занесем в очередь исходную вершину. Затем, пока очередь не пуста, будем извлекать первый элемент из очереди и добавлять в конец все не посещенные смежные с ним вершины.
Пусть задан невзвешенный ориентированный граф <tex> G === Реализация===Входные данные: vector (V, E) < vector/tex>, в котором выделена исходная вершина <inttex> > g; // граф, реализованный с помощью списка смежности int n; // число вершин int s; <// стартовая вершина tex>. Требуется найти длину кратчайшего пути (если таковой имеется) от одной заданной вершины везде нумеруются с нуля) // чтение до другой. Частным случаем указанного графа является невзвешенный неориентированный граф, т.е.граф, в котором для каждого ребра найдется обратное, соединяющее те же вершины в другом направлении.
Сам обход: queueДля алгоритма нам потребуются [[Очередь|очередь]] и множество посещенных вершин <tex> was </tex>, которые изначально содержат одну вершину <inttex> q; q.push (s); vector<bool/tex> used (n); used[s] = true; while (!q.empty()) { int На каждом шагу алгоритм берет из начала очереди вершину <tex> v = q.front(); q.pop(); for (size_t i=0; i<g[/tex> и добавляет все непосещенные смежные с <tex> v].size(); ++i) { int to = g[v][i]; if (!used[to]) { used[to] = true; q.push (to); } } }== Практические применения ==* Волновой алгоритм </tex> вершины в трассировке печатных плат;* Поиск увеличивающего пути <tex> was </tex> и в Форда-Фалкерсона конец очереди. Если очередь пуста, то алгоритм|алгоритме Форда-Фалкерсон (алгоритм Эдмондса-Карпа)завершает работу.
== Литература Анализ времени работы ==* Ананий Оценим время работы для входного графа <tex>G = (V, E)</tex>, где множество ребер <tex> E </tex> представлено списком смежности. В очередь добавляются только непосещенные вершины, поэтому каждая вершина посещается не более одного раза. Операции внесения в очередь и удаления из нее требуют <tex> O(1) </tex> времени, так что общее время работы с очередью составляет <tex> O(|V|) </tex> операций. Для каждой вершины <tex> v </tex> рассматривается не более <tex> \mathrm{deg}(v) </tex> ребер, инцидентных ей. Так как <tex> \sum\limits_{v \in V} \mathrm{deg}(v) = 2|E| </tex>, то время, используемое на работу с ребрами, составляет <tex> O(|E|) </tex>. Поэтому общее время работы алгоритма поиска в ширину — <tex> O(|V| + |E|) </tex>. == Корректность == {{Утверждение|statement=Вочереди поиска в ширину расстояние вершин до <tex>s</tex> монотонно неубывает.|proof=Докажем это утверждение индукцией по числу выполненных алгоритмом шагов. Левитин Глава 5 Введем дополнительный инвариант: у любых двух вершин из очереди, расстояние до <tex> s </tex> отличается не более чем на <tex> 1 </tex>.  '''База''': изначально очередь содержит только одну вершину <tex> s </tex>. Метод уменьшения размера задачи '''Переход''': пусть после <tex> i-й </tex> итерации в очереди <tex> a + 1 </tex> вершин с расстоянием <tex> x </tex> и <tex> b </tex> вершин с расстоянием <tex> x + 1 </tex>.  Рассмотрим <tex> i-ю </tex> итерацию. Из очереди достаем вершину <tex> v </tex>, с расстоянием <tex> x </tex>. Пусть у <tex>v</tex> есть <tex>r </tex> непосещенных смежных вершин. Тогда, после их добавления, в очереди находится <tex> a </tex> вершин с расстоянием <tex> x </tex> и, после них, <tex> b + r </tex> вершин с расстоянием <tex> x + 1 </tex>.  Оба инварианта сохранились, <tex> \Rightarrow </tex> после любого шага алгоритма элементы в очереди неубывают. }} {{Теорема|statement=Алгоритм поиска в ширину в невзвешенном графе находит длины кратчайших путей до всех достижимых вершин.|proof=Допустим, что это не так. Выберем из вершин, для которых кратчайшие пути от <tex> s </tex> найдены некорректно, ту, настоящее расстояние до которой минимально. Пусть это вершина <tex> u </tex>, и она имеет своим предком в дереве обхода в ширину <tex> v </tex>, а предок в кратчайшем пути до <tex> u </tex> — вершина <tex> w </tex>. Так как <tex> w </tex> — предок <tex> u </tex> в кратчайшем пути, то <tex> \rho(s, u) = \rho(s, w) + 1 > \rho(s, w) </tex>, и расстояние до <tex> w </tex> найдено верно, <tex> \rho(s, w) = d[w] </tex>. Значит, <tex> \rho(s, u) = d[w] + 1 </tex>. Так как <tex> v </tex> — предок <tex> u </tex> в дереве обхода в ширину, то <tex> d[u] = d[v] + 1 </tex>. Расстояние до <tex> u </tex> найдено некорректно, поэтому <tex> \rho(s, u) < d[u] </tex>. Подставляя сюда два последних равенства, получаем <tex> d[w] + 1 < d[v] + 1 </tex>, то есть, <tex> d[w] < d[v] </tex>. Из ранее доказанной леммы следует, что в этом случае вершина <tex> w </tex> попала в очередь и была обработана раньше, чем <tex> v </tex>. Но она соединена с <tex> u </tex>, значит, <tex> v </tex> не может быть предком <tex> u </tex> в дереве обхода в ширину, мы пришли к противоречию, следовательно, найденные расстояния до всех вершин являются кратчайшими.}} == Дерево обхода в ширину ==  Поиск в ширину также может построить [[Дерево, эквивалентные определения|дерево]] поиска в ширину. Изначально оно состоит из одного корня <tex> s </tex>. Когда мы добавляем непосещенную вершину в очередь, то добавляем ее и ребро, по которому мы до нее дошли, в дерево. Поскольку каждая вершина может быть посещена не более одного раза, она имеет не более одного родителя. После окончания работы алгоритма для каждой достижимой из <tex> s </ Алгоритмы: введение tex> вершины <tex> t </tex> путь в дереве поиска в ширину соответствует кратчайшему пути от <tex> s </tex> до <tex> t </tex> в разработку <tex> G </tex>. == Реализация == Предложенная ниже функция возвращает кратчайшее расстояние между двумя вершинами.*<tex> \mathtt{source} </tex> — исходная вершина*<tex> \mathtt{destination} </tex> — конечная вершина*<tex> \mathtt{G} </tex> — граф, состоящий из списка вершин <tex> \mathtt{V} </tex> и анализ списка смежности <tex> \mathtt{E} </tex>. Вершины нумеруются целыми числами.*<tex> \mathtt{Q} </tex> — очередь.*В поле <tex> \mathtt{d[u]} </tex> хранится расстояние от <tex> \mathtt{source} </tex> до <tex> \mathtt{u} </tex>.  '''int''' '''BFS'''(G: (V, E), source: '''int''', destination: '''int'''): d = '''int'''[|V|] '''fill'''(d, <tex> \infty </tex>) d[source] = 0 Q = Introduction to The Design and Analysis of Aigorithms<tex> \varnothing </tex> Q. — Мpush(source) '''while''' Q <tex> \ne \varnothing </tex> u = Q.pop() '''for''' v: «Вильямс»(u, v) '''in''' E '''if''' d[v] == <tex> \infty </tex> d[v] = d[u] + 1 Q.push(v) '''return''' d[destination] Если требуется найти расстояние лишь между двумя вершинами, из функции можно выйти, 2006как только будет установлено значение <tex> \mathtt{d[destination]} </tex>. — СЕще одна оптимизация может быть проведена при помощи метода [[Meet-in-the-middle#Задача о нахождении кратчайшего расстояния между двумя вершинами в графе|meet-in-the-middle]]. 215 == Вариации алгоритма ===== 0-2181 BFS ===Пусть в графе разрешены ребра веса <tex> 0 </tex> и <tex> 1 </tex>, необходимо найти кратчайший путь между двумя вершинами. Для решения данной задачи модифицируем приведенный выше алгоритм следующим образом:  Вместо очереди будем использовать [[Персистентный_дек|дек]] (или можно даже steque). — ISBN Если рассматриваемое ее ребро имеет вес <tex> 0</tex>, то будем добавлять вершину в начало, а иначе в конец. После этого добавления, дополнительный введенный инвариант в доказательстве [[#Корректность | расположения элементов в деке в порядке неубывания]] продолжает выполняться, поэтому порядок в деке сохраняется. И, соответственно, релаксируем расстояние до всех смежных вершин и, при успешной релаксации, добавляем их в дек.  Таким образом, в начале дека всегда будет вершина, расстояние до которой меньше либо равно расстоянию до остальных вершин дека, и инвариант [[#Корректность | расположения элементов в деке в порядке неубывания]] сохраняется. Значит, алгоритм корректен на том же основании, что и обычный BFS. Очевидно, что каждая вершина войдет в дек не более двух раз, значит, асимптотика у данного алгоритма та же, что и у обычного BFS. === 1-k BFS ===Пусть в графе разрешены ребра целочисленного веса из отрезка <tex>1 \ldots k</tex>, необходимо найти кратчайший путь между двумя вершинами. Представим ребро <tex>uv</tex> веса <tex>m</tex> как последовательность ребер <tex>uu_1u_2 \ldots u_{m -2011}v</tex> (где <tex>u_1 \ldots u_{m -743951}</tex> — новые вершины). Применим данную операцию ко всем ребрам графа <tex> G </tex>. Получим граф, состоящий (в худшем случае) из <tex>k|E|</tex> ребер и <tex>|V| + (k -71)|E|</tex> вершин. Для нахождения кратчайшего пути следует запустить BFS на новом графе. Данный алгоритм будет иметь асимптотику <tex> O(|V| + k|E|) </tex>. == См. также == * [[Обход в глубину, цвета вершин]]* [[Алгоритм Дейкстры]]* [[Теория графов]] == Источники информации == *Томас Х. Кормен и др, Чарльз И. Лейзерсон, Рональд Л. Ривест, Клиффорд Штайн Алгоритмы: построение и анализ = INTRODUCTION TO ALGORITHMS. — 2-е изд. — М.: «Вильямс», 20062007. — Сс. 1296459. — ISBN 05-8489-0857-4* [http://e-maxx.ru/algo/bfs MAXimal :: algo :: Поиск в ширину]* [[wikipedia:en:Breadth-first_search| Wikipedia {{---}} Breadth-first search]]* [[wikipedia:ru:Поиск_в_ширину| Wikipedia {{-07-013151-1}} Поиск в ширину]]* [http://rain.ifmo.ru/cat/view.php/vis/graph-general/bfs-2002 Визуализатор алгоритма]  [[Категория: Алгоритмы и структуры данных]][[Категория: Кратчайшие пути в графах]]
1632
правки

Навигация