Эффективно найти все связанные индуцированные подграфы
существует ли эффективный (*) алгоритм для поиска всех связанных (индуцированных) подграфов Связного неориентированного вершинного графа?
(*) Я понимаю, что в общем случае любой такой алгоритм может иметь сложность O (2^n), потому что для клики (Kn) существует 2^n связанных подграфов. Однако графики, с которыми я обычно имею дело, будут иметь гораздо меньше связанных подграфов, поэтому я ищу способ их генерации без необходимости рассматривать все 2^n подграфов и бросать прочь те, которые не связаны (как в решении этот вопрос).
алгоритм, который имеет время работы, линейное по числу решений (т. е. он может генерировать решения непосредственно из структуры графа, не тратя время на рассмотрение всех не-решений), очевидно, был бы идеальным. Дополнительный шаг, который является полиномиальным по числу узлов, тоже будет прекрасным (например, предварительное вычисление транзитивного замыкания графа-не то, что я думаю это помогло бы в данном случае).
альтернативно, доказательство того, что такого решения нет, по крайней мере, избавило бы меня от моих страданий.
1 ответов
в рекурсивном псевдокоде алгоритм 2^n равен
GenerateAndTest(verticesNotYetConsidered, subsetSoFar):
if verticesNotYetConsidered is empty:
yield subsetSoFar if it induces a connected subgraph
else:
choose a vertex v in verticesNotYetConsidered
GenerateAndTest(verticesNotYetConsidered - {v}, subsetSoFar)
GenerateAndTest(verticesNotYetConsidered - {v}, subsetSoFar union {v})
не имеет значения, какая вершина V выбрана; мы даже можем выбирать по-разному в двух братских вызовах. Мы используем эту свободу для получения почти линейного алгоритма Времени (N раз больше числа решений) путем обрезки дерева рекурсии.
если subsetSoFar
пусто, тогда выбор по-прежнему не ограничен. В противном случае мы выбираем v
быть рядом с одной из вершин в subsetSoFar
. Если нет такого v
существует, мы уступаем subsetSoFar
и return, так как в этом поддереве нет других решений.
обратите внимание на новый инвариант, что subsetSoFar
всегда подключен, поэтому мы можем исключить явный тест подключения. Мы делаем O (n) работу на каждом узле дерева рекурсии(наивно O (n^2), но мы можем поддерживать множество соседних вершин постепенно), которое является полным двоичным и чьи листья дают ровно одно решение, поэтому общая работа такова, как утверждалось (напомним, что число внутренних вершин узлы на один меньше, чем количество листьев).
из-за нового инварианта не получается отключенного подграфа.
каждый подключенный подграф выдается. Для набора вершин S, который индуцирует связный подграф, следуйте ветвям, которые согласуются с S. Для правильного подмножества S невозможно не иметь смежности с остальной частью S, поэтому S не обрезается.
новый псевдокод выглядит следующим образом. N(v)
обозначает множество соседей v
.
GenerateConnectedSubgraphs(verticesNotYetConsidered, subsetSoFar, neighbors):
if subsetSoFar is empty:
let candidates = verticesNotYetConsidered
else
let candidates = verticesNotYetConsidered intersect neighbors
if candidates is empty:
yield subsetSoFar
else:
choose a vertex v from candidates
GenerateConnectedSubgraphs(verticesNotYetConsidered - {v},
subsetSoFar,
neighbors)
GenerateConnectedSubgraphs(verticesNotYetConsidered - {v},
subsetSoFar union {v},
neighbors union N(v))
EDIT: для графиков максимальной степени O (1) мы можем сделать это действительно линейным временем, поддерживая verticesNotYetConsidered intersect neighbors
, чего я не делал для ясности. Эта оптимизация, вероятно, не стоит многого, если вы используете word-parallelism, представляя граф как матрицу смежности, где каждая строка хранится как растровое изображение одного или двух слов.