Алгоритм нахождения Гамильтонова цикла в условиях теорем Дирака и Оре — различия между версиями
| Ak57 (обсуждение | вклад) м (→Доказательство алгоритма) | Ak57 (обсуждение | вклад)   (→Псевдокод) | ||
| Строка 13: | Строка 13: | ||
| |   | |   | ||
| − |    for <tex>v_i \in P </tex>                              //перебираем все вершины перестановки <tex>P</tex> | + |    for <tex>v_i \in P </tex>                              // перебираем все вершины перестановки <tex>P</tex> | 
| − |      if <tex> v_i v_{i+1} \notin \mathbb{E} </tex>                         //если нет ребра между <tex>v_i v_{i+1} </tex> | + |      if <tex> v_i v_{i+1} \notin \mathbb{E} </tex>                         // если нет ребра между <tex>v_i v_{i+1} </tex> | 
| − |        for <tex>v_j \in \mathbb{V} \setminus \{v_i, v_{i + 1}\}</tex>              //перебираем все остальные вершины   | + |        for <tex>v_j \in \mathbb{V} \setminus \{v_i, v_{i + 1}\}</tex>              // перебираем все остальные вершины   | 
| − |          if <tex>v_i v_j \in \mathbb{E}\</tex> && <tex> v_{i+1} v_{j+1} \in \mathbb{E}</tex>      //если есть ребра <tex>v_i v_j,\ v_{i+1} v_{j+1} </tex> | + |          if <tex>v_i v_j \in \mathbb{E}\</tex> && <tex> v_{i+1} v_{j+1} \in \mathbb{E}</tex>      // если есть ребра <tex>v_i v_j,\ v_{i+1} v_{j+1} </tex> | 
| − |            reverse_subsequence(<tex>P, i+1, j</tex>)  //разворачиваем часть перестановки <tex>P</tex> от i+1 позиции до j | + |            reverse_subsequence(<tex>P, i+1, j</tex>)  // разворачиваем часть перестановки <tex>P</tex> от i+1 позиции до j | 
| − |            break                           //переходим к следующей итерации внешнего for                         | + |            break                           // переходим к следующей итерации внешнего for                         | 
| |width = "310px" | | |width = "310px" | | ||
Версия 18:57, 6 ноября 2013
Описание алгоритма
Алгоритм находит гамильтонов цикл в неориентированном графе , если выполняются условия теоремы Оре или выполнена теорема Дирака. Рассмотрим перестановку вершин , где . Если между каждой парой соседних вершин в перестановке существует ребро, то мы получили Гамильтонов цикл. В противном случае, начиная с пары , начнем последовательно рассматривать пары соседних вершин , пока .
- Если между ними есть ребро, то переходим к следующей паре вершин .
-  Если же ребра нет, то найдем такую вершину  (то, что она всегда существует, будет показано ниже), что , и существуют ребра   и  (Если  , то за  считаем ).
- Если то перевернем часть перестановки от до (включительно).
- Если обменяем в перестановке элементы на позициях и , где . Например, если , то и поменяются местами, а останется на месте.
 
Псевдокод
| for // перебираем все вершины перестановки if // если нет ребра между for // перебираем все остальные вершины if && // если есть ребра reverse_subsequence() // разворачиваем часть перестановки от i+1 позиции до j break // переходим к следующей итерации внешнего for | 
Доказательство алгоритма
Заметим, что поскольку мы сделали нашу перестановку в виде зацикленного списка, то мы можем рассматривать перебор все пар соседних в перестановке вершин, как сдвиг указателя на начало списка. Тогда будем сдвигать указатель на нашу перестановку так, чтобы она начиналась с рассматриваемой пары . Если теперь между первыми двумя вершинами есть ребро, то можем переходить к рассмотрению следующей пары, так как в этом случае мы ничего не делаем. Если же ребра нет, то докажем, что обязательно найдется вершина , такая что .
Пусть и . Тогда , откуда . Но по условию теоремы Оре или теоремы Дирака, в зависимости от наших начальных условий. А значит , следовательно искомая вершина обязательно найдется. Поскольку каждый раз, когда у нас нет ребра между двумя обрабатываемыми вершинами, мы переворачиваем нашу последовательность так, чтобы после переворота и становились связанными ребром, то, рассмотрев все пары вершин в последовательности, мы добьемся того, что любые две соседние пары вершин будут связаны ребром, а это и значит что мы нашли цикл.
