Временная сложность перечисления n-вершинного подграфа
У меня есть алгоритм для создания списка всех возможных подграфов на P вершинах через данную вершину. Это не идеально, но я думаю, что это должно работать хорошо. Проблема в том, что я теряюсь, когда пытаюсь вычислить сложность его времени.
Я придумал что-то вроде T(p) = 2^d + 2^d * (n * T(p-1) )
, где d=Δ(G), p=#vertices required, n=|V|
, Это действительно просто предположение. Кто-нибудь может мне с этим помочь?
Используемый алгоритм powerSet() должен быть O(2^d)
или же O(d*2^d)
,
private void connectedGraphsOnNVertices(int n, Set<Node> connectedSoFar, Set<Node> neighbours, List<Set<Node>> graphList) {
if (n==1) return;
for (Set<Node> combination : powerSet(neighbours)) {
if (connectedSoFar.size() + combination.size() > n || combination.size() == 0) {
continue;
} else if (connectedSoFar.size() + combination.size() == n) {
Set<Node> newGraph = new HashSet<Node>();
newGraph.addAll(connectedSoFar);
newGraph.addAll(combination);
graphList.add(newGraph);
continue;
}
connectedSoFar.addAll(combination);
for (Node node: combination) {
Set<Node> k = new HashSet<Node>(node.getNeighbours());
connectedGraphsOnNVertices(n, connectedSoFar, k, graphList);
}
connectedSoFar.removeAll(combination);
}
}
1 ответ
Похоже, что в алгоритме есть ошибка, потому что после рекурсивного вызова, возможно, что узлы, которые появляются в комбинации, также появятся в connectedSoFar, поэтому проверка того, что connectedSoFar.size () + сочетание.size () равно n, кажется неправильной, так как может считать узел дважды.
В любом случае, для анализа алгоритма у вас есть 2d элементов в powerset; каждая операция в ветви "elase" занимает O(n) времени, потому что connectedSoFar и комбинация вместе не могут содержать более n узлов. Добавление элементов в connectedSoFar тогда занимает O(n log n) времени, потому что | комбинация | ≤ н. Итерация по узлам комбинации происходит O(n) раз; внутри него есть операция O(d) для построения хэш-множества k, а затем рекурсивный вызов.
Обозначим тогда сложность процедуры через X(n), где n - параметр. У тебя есть
X(n) ~ 2d (n + n log n + n (d + X (n - 1)))
потому что в рекурсивном вызове вы добавили в граф хотя бы одну вершину, поэтому на практике параметр n в рекурсивном вызове уменьшается практически как минимум на одну.
Упростите это до
X(n) ~ 2d (n (1 + d + log n + X (n - 1)))
потому что d постоянная, отметьте D = 2d, исключите постоянную 1, и вы получите
X(n) ~ D n (d + log n + X(n - 1))
который вы можете проанализировать как
X(n) ~ (2d)n n! (d + log n)
показывая, что твой алгоритм действительно является временным боровом:)