Изменения

Перейти к: навигация, поиск
Псевдокод
__TOC__
{{Задача
|definition = Пусть дан граф <tex>G = \left \langle {V, E} \right \rangle</tex>, удовлетворяющий условию [[Теорема Оре|теоремы Оре]] или [[Теорема Дирака|теоремы Дирака]]. Требуется найти в нем гамильтонов цикл.
}}
== Описание алгоритма ==
Пусть у нас есть граф <tex>\mathbb{G} = \left \langle \mathbb{V, E} \right \rangle</tex>, удовлетворяющий условию [[Теорема Дирака|теоремы Оре]] или [[Теорема Дирака|теоремы Дирака]], и требуется найти в нем гамильтонов цикл. Поступим следующим образом: заведем очередь и положим в нее все вершины нашего графа(не важно в каком порядке). Теперь <tex>n = \left | \mathbb{V}\right |</tex> раз будем делать следующую операцию:
Поступим следующим образом: заведем очередь и положим в нее все вершины нашего графа (не важно в каком порядке). Пусть <tex> n = \left | V \right |</tex>. Тогда <tex>n(n -1)</tex> раз будем делать следующую операцию: * Пусть <tex> v_1 </tex> {{---}} это голова очереди, <tex> v_2 </tex> {{---}} следующая за ней вершина и так далее. Если между первой (здесь и далее первая вершина - вершина в голове очереди) и второй вершиной в очереди есть ребро в графе <tex>\mathbb{G}</tex>, то перемещаем первую вершину в конец очереди и переходим к следующей итерации.* Если между первой и второй вершиной в очереди ребра нет, то найдем вершину <tex>v_i</tex>, где <tex>i > 2</tex>, такую что, ребра <tex>v_1v_i, v_2v_{i+1} \in \mathbb{E}</tex> (так как у нас для графа выполнена либо [[Теорема Оре|теорема Оре]], либо [[Теорема Дирака|теорема Дирака]], то такая вершина обязательно найдется; чуть позже мы докажем это докажем явно). После чего поменяем в очереди местами вершины <tex>v_2</tex> и <tex>v_i</tex>, <tex>v_3</tex> и <tex>v_{i-1}</tex>, <tex>v_{2+j} </tex> и <tex>v_{i-j}</tex>, и так далее, пока <tex>2 + j < i - j</tex> (то есть <tex>j</tex> пробегает все значения от <tex>0 </tex> до значения заданного неравенством). Теперь у нас появилось ребро между первой и второй вершинами в очереди (теперь вторая вершина, это та, которая была до разворота на <tex>i</tex>-й позиции), а также, гарантированно существует ребро между <tex>i</tex>-й и <tex>(i+1)</tex>-й вершинами очереди. После этого, так же как и в первом случае, оправляем первую вершину в конец очереди.
Таким образом после <tex>n</tex> итераций, мы получаем последовательность (вершины лежащие в очереди), где любые 2 соседние вершины соединены ребром, все вершины графа находятся в этой последовательности, и более того, каждая ровно один раз, а также существует ребро между последней и первой вершинами очереди, а это и значит, что мы решили поставленную задачу.
== Псевдокод ==
Функция <tex>\mathtt{findHamiltonianCycle}</tex> получает на вход граф <tex> G </tex > и находит гамильтонов цикл в нем.
 
* <tex> queue </tex> {{---}} очередь вершин графа <tex>G = \left \langle {V, E} \right \rangle</tex>
{| width = 100%
|-
|
g[][] - булевская матрица смежности '''function''' findHamiltonianCycle(<tex>\left \langle {V, E} \right \rangle</tex>): Queue queue '''for''' <tex> v \in V</tex>: <font color = "green">// создаем Добавляем все вершины графа в очередь</font> for i = 0 to n - 1 queue.pushBack(<tex>v[i]</tex>) // добавляем в очередь все вершины графа '''for ''' k = 0 to ..n * (n - 1 // пока не проделано нужное количество итераций) '''if not g[''' (queue.at(0), queue.at(1)] ) <tex> \notin E</tex> <font color = "green">// проверяем Проверяем существования ребра между первой и второй вершинами очереди</font> i = 2 '''while not g[''' (queue.at(0), queue.at(i)] ) <tex> \notin E</tex> '''or not g[''' (queue.at(1), queue.at(i + 1)] ) <tex> \notin E</tex> i++ <font color = "green">/ ищем / Ищем индекс удовлетворяющую условию вершины</font> i++ queue.swapSubQueue(21, i) <font color = "green">// разворачиваем Разворачиваем часть перестановки от 21-й до найденной позиции включительно</font> queue.pushBack(queue.top()) // Добавляем первую вершину в конец очереди queue.pop() // а из начала очереди удаляем |width = "310px" |
|}
== Доказательство алгоритма ==
Для доказательства корректности алгоритма достаточно показать:
* {{Лемма|statement=Каждый раз, когда нам надо искать вершину <tex>v_i</tex>, где <tex>i > 2</tex>, такую что <tex>v_1v_i, v_2v_{i+1} \in \mathbb{E}</tex>, такая вершина действительно существует.* После |proof=Рассмотрим множество <tex>S = \{i\mid v_1v_i \in E\}</tex>, состоящее из индексов вершин, смежных с <tex>v_1</tex>, и множество <tex>T = \{i+1 \mid v_2v_{i+1} \in E\}</tex>, индексов вершин смежных с <tex>v_2</tex>. Заметим, что <tex>S \subset \{3, 4, \ldots, n\}</tex>, а <tex>T \subset \{2, 3, \ldots, n - 1\}</tex>, тогда <tex>S\cup T\subset \{2, 3, \ldots, n\} </tex>, а значит <tex>\left\vert S\cup T\right\vert \leqslant n-1</tex> итераций между каждой парой соседних вершин очереди , в то же время <tex>\left\vert S \right\vert + \left\vert T \right\vert = \operatorname{deg} v_1 + \operatorname{deg} v_2 \geqslant n</tex> (по условию [[Теорема Оре|теоремы Оре]] или [[Теорема Дирака|теоремы Дирака]]). Из этого следует, что <tex>S\cap T\ne \varnothing</tex>, а это и значит, что искомая вершина существует ребро.}}
Докажем первое. Рассмотрим множество {{Лемма|statement=После <tex>S = \{i\mid v_1v_i \in \mathbb{E}\}n(n - 1)</tex>итераций между каждой парой соседних вершин очереди существует ребро.|proof=Достаточно заметить, что каждую итерацию алгоритма, состоящее из вершинмы, в случае отсутствия ребра, смежных с между <tex>v_1</tex>, и множество <tex>T = \v_{i+1 \mid v_2v_{i+1} \in \mathbb{E}\2}</tex>, увеличиваем количество пар соседних в очереди вершин смежных с <tex>v_2</tex>. Заметим, что <tex>S \subset \{3, 4между которыми есть ребро,...,n\}как минимум на </tex>, а <tex>T \subset \{2, 3,...,n - 1\}</tex>(это прямое следствие условия поиска нужной вершины, в случае отсутствия ребра), тогда для поиска такой пары требуется не более <tex>S\cup T\subset \{2, 3,...,n\} </tex>, а значит итераций. Таких пар изначально не более <tex>\left\vert S\cup T\right\vert \le n-1</tex>, в то же время <tex>\left\vert S \right\vert + \left\vert T \right\vert = \operatorname{deg} v_1 + \operatorname{deg} v_2 \ge n</tex> (по условию [[Теорема Оре|теоремы Оре]] или [[Теорема Дирака|теоремы Дирака]]). Из этого откуда следует, что после <tex>S\cap T\ne \varnothingn</tex>итераций, а это и значит, что искомая вершина существуетвторое условие будет выполнено.}}
Для доказательства второй части, достаточно заметить, что каждую итерацию алгоритма, мы, в случае отсутствия ребра, между <tex>v_2</tex> и <tex>v_{2}</tex> увеличиваем количество пар соседних в очереди вершин, между которыми есть ребро, как минимум на 1 (это прямое следствие условия поиска нужной вершины, в случае отсутствия ребра), а таких пар изначально не более <tex>n</tex>{Теорема|statement=Алгоритм находит гамильтонов цикл. Откуда |proof=Из предыдущих лемм следует, что после <tex>n</tex> итераций, второе условие будет выполненокорректность алгоритма.}}
== Сложность алгоритма ==
Алгоритм Поиск вершины, удовлетворяющей заданному условию работает за <tex>O(n^2)</tex>. Действительно, количество итераций внешнего цикла а таких поисков будет осуществлено не более чем <tex>\mathrm{for}n</tex> всегда равно . Оставшиеся <tex>n(n - 2)</tex>. Поиск вершины, удовлетворяющей заданному условию тоже работает итерации выполняются за <tex>O(n1)</tex>, итого время работы .Тогда алгоритм выполняется за <tex>O(n^2)</tex>.
== См.также ==
*[[Теорема Оре]]
*[[теорема Дирака|Теорема Дирака]]
*[[Очередь]]
 
== Источники информации ==
*[http://rain.ifmo.ru/cat/view.php/theory/graph-circuits-cuts/hamiltonian-2005 Дискретная математика: Алгоритмы {{---}} Гамильтоновы графы]
[[Категория: Алгоритмы и структуры данных]]
[[Категория: Обходы графов]]
[[Категория: Гамильтоновы графы]]
Анонимный участник

Навигация