Проблема алгоритма

Граф - это подграф графа, в котором любая вершина связана с остальными вершинами.

В задаче k вход является неориентированным графом и числом k, а выход - размером clof k, если таковой существует (или, иногда, всем cl размера k)

2 ответа

Предположим без ограничения общности, что узлы графа идентифицируются целыми числами от 0 до N-1 (без потери общности, потому что если каждый узел должен нести другую информацию, вы можете иметь массив / вектор / список из объектов N узлов, и принять эти целые числа как индексы в рассматриваемом массиве). Связность графа может быть обозначена, например, отображением каждого узла на набор, который является непосредственными соседями узла.

Чтобы проверить соединение, а не непосредственную смежность, вам скорее понадобится другое отображение - транзитивное замыкание отображения непосредственных соседей. Конечно, есть хорошие алгоритмы для этого (см., Например, исходный код Python для пакета networkx), но грубый метод просто начнется с копирования непосредственного сопоставления смежности в сопоставление соединения, а затем итеративно расширяет наборы до одной итерации. больше не расширяет набор.

Например, пример грубой силы на Python 2.6:

import copy

def transitive_closure(immediate_neighbors):
  result = copy.deepcopy(immediate_neighbors)
  changes = True
  while changes:
    changes = False
    for node in result:
      newset = set(result[node])
      for neighbor in result[node]:
        newset.update(result[neighbor])
      if newset != result[node]:
        changes = True
        result[node] = newset
  return result

immediate = {0:[1,2], 1:[0], 2:[0], 3:[4], 4:[3]}
connections = transitive_closure(immediate)
for node in sorted(connections):
  print node, sorted(connections[node])

печатает:

0 [0, 1, 2]
1 [0, 1, 2]
2 [0, 1, 2]
3 [3, 4]
4 [3, 4]

С connections словарь под рукой, все, что нам нужно сделать, это изучить каждую комбинацию k узлы (например, в Python 2.6 или выше, itertools.combinations(range(N), k) дает нам эти комбинации): это будет клика, если это подмножество (не обязательно правильное подмножество) набора элементов, связанных с любым из его членов.

Так, например, приведенный выше код можно продолжить, чтобы показать все 2-клики:

import itertools
cliques = set()
for somenodes in itertools.combinations(range(5), 2):
  if set(somenodes) <= connections[somenodes[0]]:
    cliques.add(somenodes)
print '%d cliques:' % len(cliques)
for c in sorted(cliques): print ' ', c

который печатает, с данными, использованными в предыдущем примере:

4 cliques:
  (0, 1)
  (0, 2)
  (1, 2)
  (3, 4)

Для подходов без грубой силы я рекомендую снова изучить networkx Исходный код, на который я указал ранее.

Хорошо, нумеруйте вершины 1 ... n и преобразуйте граф в матрицу логической смежности - 1 в точке (i,j), что означает, что i и j связаны. В неориентированном графе матрица должна быть симметричной. Теперь ваша задача сводится к поиску "квадрата" размером k x k со всеми 1 с. "Квадрат" забавен тем, что строки и столбцы не обязательно должны быть смежными друг с другом. Чтобы получить некоторый квадрат, вы начинаете с n строк, n столбцов, удаляете (nk) строк и столбцов - и вуаля! Ты понял.

Теперь каждый уникальный квадрат всех 1 будет соответствовать клике. Чтобы проверить уникальность, представьте квадрат как неизменный кортеж ((i1,j1), (i2, j2) ... (ik,jk)) (нотация Python).

В Python вы можете добавить кортежи в неупорядоченный набор и спросить набор, содержит ли он уже элемент, который мы ищем.

Другие вопросы по тегам