Гамильтоновы графы — различия между версиями
SergeyBud (обсуждение | вклад)  (→Основные определения)  | 
				 (→Алгоритм нахождения гамильтового цикла)  | 
				||
| Строка 90: | Строка 90: | ||
Приведём два алгоритма поиска гамильтонова цикла.  | Приведём два алгоритма поиска гамильтонова цикла.  | ||
| − |   bool check_hamiltonian(graph g, bool[] used, int vert, int count, int[] next):  | + |   '''bool''' check_hamiltonian(graph g, '''bool'''[] used, '''int''' vert, '''int''' count, '''int'''[] next):  | 
| − |     if (count == g.vertices)  | + |     '''if''' (count == g.vertices)  | 
      next[vert] = 0  |       next[vert] = 0  | ||
| − |       return (vert; 0) in g.edges  | + |       '''return''' (vert; 0) '''in''' g.edges  | 
| − |     for   | + |     '''for''' i = 0 '''to''' g.vertices  | 
| − |       if (!used[i] && (vert; i) in g.edges)  | + |       '''if''' (!used[i] && (vert; i) in g.edges)  | 
        used[i] = true  |         used[i] = true  | ||
        next[vert] = i  |         next[vert] = i  | ||
| − |         if (check_hamiltonian(g, used, i, count + 1, next))  | + |         '''if''' (check_hamiltonian(g, used, i, count + 1, next))  | 
| − |           return true  | + |           '''return''' true  | 
        used[i] = false  |         used[i] = false  | ||
| − |     return false  | + |     '''return''' false  | 
* used — отметки о посещении  | * used — отметки о посещении  | ||
| Строка 111: | Строка 111: | ||
Приведём алгоритм, основанный на динамическом программировании, который работает значительно быстрее. Алгоритм основан на следующей идее: будем для каждой пары из подмножества вершин и вершины считать, существует ли гамильтонов путь для этого подмножества вершин, заканчивающихся в выделенной вершине. Суммарно таких состояний будет <tex>O(n2^n)</tex>, для обсчёта каждого из них требуется <tex>O(n)</tex> времени, то есть, суммарно алгоритм работает за <tex>O(n^22^n)</tex> времени. Псевдокод, реализующий этот алгоритм, приведён ниже:  | Приведём алгоритм, основанный на динамическом программировании, который работает значительно быстрее. Алгоритм основан на следующей идее: будем для каждой пары из подмножества вершин и вершины считать, существует ли гамильтонов путь для этого подмножества вершин, заканчивающихся в выделенной вершине. Суммарно таких состояний будет <tex>O(n2^n)</tex>, для обсчёта каждого из них требуется <tex>O(n)</tex> времени, то есть, суммарно алгоритм работает за <tex>O(n^22^n)</tex> времени. Псевдокод, реализующий этот алгоритм, приведён ниже:  | ||
| − |   bool[][] get_dp_table(graph g):  | + |   '''bool'''[][] get_dp_table(graph g):  | 
| − |     int n = g.vertices  | + |     '''int''' n = g.vertices  | 
| − |     bool[][] result = new int[1 << n][n]  | + |     '''bool'''[][] result = new int[1 << n][n]  | 
| − |     for   | + |     '''for'''  i = 0 '''to''' n  | 
| − |       result[1 << i][i] = (0; i) in g.edges;  | + |       '''result'''[1 << i][i] = (0; i) '''in''' g.edges;  | 
| − |     for   | + |     '''for'''  i = 1 '''to''' 1 << n  | 
| − |       if (count(i) == 1)  | + |       '''if''' (count(i) == 1)  | 
| − |         continue  | + |         '''continue'''  | 
| − |       for   | + |       '''for'''  j = 0 '''to''' n  | 
| − |         if ((1 << j) & i != 0)  | + |         '''if''' ((1 << j) & i != 0)  | 
| − |           for   | + |           '''for''' k = 0 '''to''' n  | 
| − |             if (k != j && (1 << k) & i != 0)  | + |             '''if''' (k != j && (1 << k) & i != 0)  | 
| − |               result[i][j] = result[(1 << j) ^ i][k] && (k; j) in g.edges  | + |               result[i][j] = result[(1 << j) ^ i][k] && (k; j) '''in''' g.edges  | 
| − |     return result  | + |     '''return''' result  | 
В приведённом выше коде считаем, что n меньше количества бит в числовом типе данных, для операций над множествами используются побитовые логические операции в синтаксисе языка C. Функция count считает количество единичных бит в числе (она проста в реализации, но не относится к алгоритма, поэтому не приводится). Граф гамильтонов тогда, когда dp[(1 << n) - 1][i] && (i; 0) <tex>\in</tex> g.edges для некоторого i.  | В приведённом выше коде считаем, что n меньше количества бит в числовом типе данных, для операций над множествами используются побитовые логические операции в синтаксисе языка C. Функция count считает количество единичных бит в числе (она проста в реализации, но не относится к алгоритма, поэтому не приводится). Граф гамильтонов тогда, когда dp[(1 << n) - 1][i] && (i; 0) <tex>\in</tex> g.edges для некоторого i.  | ||
Версия 03:03, 30 декабря 2015
Содержание
Основные определения
| Определение: | 
| Гамильтоновым путём (англ. Hamiltonian path) называется простой путь, приходящий через каждую вершину графа ровно один раз. | 
| Определение: | 
| Гамильтоновым циклом (англ. Hamiltonian cycle) называют замкнутый гамильтонов путь. | 
| Определение: | 
| Граф называется полугамильтоновым (англ. Semihamiltonian graph), если он содержит гамильтонов путь. | 
| Определение: | 
| Граф называется гамильтоновым (англ. Hamiltonian graph), если он содержит гамильтонов цикл. | 
Очевидно, что любой гамильтонов граф также и полугамильтонов.
Достаточные условия гамильтоновости графа
Теорема Дирака
| Теорема: | 
Если  и   для любой вершины  неориентированного графа  , то   - гамильтонов граф.  | 
Теорема Оре
| Теорема: | 
Если  и   для любых двух различных несмежных вершин  и  неориентированного графа  , то   - гамильтонов граф.  | 
Теорема Поша
| Теорема (Поша): | 
Пусть граф  имеет  вершин и выполнены следующие два условия:
 
  | 
Теорема Редеи-Камиона
| Теорема: | 
Любой сильносвязный турнир - гамильтонов.  | 
Теорема Гуйя-Ури
| Теорема (Ghouila-Houri): | 
Пусть G - сильносвязный ориентированный граф.  G - гамильтонов.  | 
Теорема Хватала
| Теорема (Хватал): | 
Пусть:
 
 Тогда если  верна импликация:   | 
Алгоритм нахождения гамильтового цикла
Приведём два алгоритма поиска гамильтонова цикла.
bool check_hamiltonian(graph g, bool[] used, int vert, int count, int[] next):
  if (count == g.vertices)
    next[vert] = 0
    return (vert; 0) in g.edges
  for i = 0 to g.vertices
    if (!used[i] && (vert; i) in g.edges)
      used[i] = true
      next[vert] = i
      if (check_hamiltonian(g, used, i, count + 1, next))
        return true
      used[i] = false
  return false
- used — отметки о посещении
 - vert — текущая вершина
 - count — количество посещённых вершин
 
Приведённая процедура работает следующим образом: перебираются всё рёбра из текущей вершины в ещё не посещённые. Чтобы проверить граф на гамильтоновость, необходимо запустить процедуру из вершины с номером 0 и параметром count = 1. Если процедура возвращает true, то в массиве next будет храниться следующая вершина на гамильтоновом цикле. Этот алгоритм в худшем случае перебирает путей, что даёт сложность работы .
Приведём алгоритм, основанный на динамическом программировании, который работает значительно быстрее. Алгоритм основан на следующей идее: будем для каждой пары из подмножества вершин и вершины считать, существует ли гамильтонов путь для этого подмножества вершин, заканчивающихся в выделенной вершине. Суммарно таких состояний будет , для обсчёта каждого из них требуется времени, то есть, суммарно алгоритм работает за времени. Псевдокод, реализующий этот алгоритм, приведён ниже:
bool[][] get_dp_table(graph g):
  int n = g.vertices
  bool[][] result = new int[1 << n][n]
  for  i = 0 to n
    result[1 << i][i] = (0; i) in g.edges;
  for  i = 1 to 1 << n
    if (count(i) == 1)
      continue
    for  j = 0 to n
      if ((1 << j) & i != 0)
        for k = 0 to n
          if (k != j && (1 << k) & i != 0)
            result[i][j] = result[(1 << j) ^ i][k] && (k; j) in g.edges
  return result
В приведённом выше коде считаем, что n меньше количества бит в числовом типе данных, для операций над множествами используются побитовые логические операции в синтаксисе языка C. Функция count считает количество единичных бит в числе (она проста в реализации, но не относится к алгоритма, поэтому не приводится). Граф гамильтонов тогда, когда dp[(1 << n) - 1][i] && (i; 0) g.edges для некоторого i.
Источники
- Харари Ф. Теория графов: Пер. с англ. / Предисл. В. П. Козырева; Под ред. Г.П.Гаврилова. Изд. 4-е. — М.: Книжный дом "ЛИБРОКОМ", 2009. — 60 с.
 - Седжвик Р. Фундаментальные алгоритмы на C++. Алгоритмы на графах. — СПб: ООО «ДиаСофтЮП», 2002.
 - Гамильтонов граф