Учитывая неориентированный граф, я хочу сгенерировать все подграфы, которые являются деревьями размера N, где размер относится к числу ребер в дереве.
Я знаю, что их много (по экспоненциально много, по крайней мере, для графиков с постоянной связностью), но это прекрасно, так как я считаю, что количество узлов и ребер делает это приемлемым для хотя бы небольших значений N (скажем, 10 или менее).
Алгоритм должен быть эффективен с точки зрения памяти, т.е. ему не обязательно иметь сразу все графики или некоторое большое их количество в памяти, так как это может превысить доступную память даже для относительно небольших графиков. Поэтому желательно использовать DFS.
Вот что я думаю, в псевдокоде, учитывая начальный график graph
и желаемую длину N
:
Выберите любую произвольную node, root
как отправную точку и вызовите alltrees(graph, N, root)
alltrees(graph, N, root)
given that node root has degree M, find all M-tuples with integer, non-negative values whose values sum to N (for example, for 3 children and N=2, you have (0,0,2), (0,2,0), (2,0,0), (0,1,1), (1,0,1), (1,1,0), I think)
for each tuple (X1, X2, ... XM) above
create a subgraph "current" initially empty
for each integer Xi in X1...XM (the current tuple)
if Xi is nonzero
add edge i incident on root to the current tree
add alltrees(graph with root removed, N-1, node adjacent to root along edge i)
add the current tree to the set of all trees
return the set of all trees
Это находит только деревья, содержащие выбранный начальный корень, поэтому теперь удалите этот node и вызовите alltrees (граф с удаленным корнем, N, новый произвольно выбранный корень) и повторите до тех пор, пока размер оставшегося графа < N (так как не будет деревьев требуемого размера).
Я также забыл, что каждый посетивший node (каждый корень для некоторого вызова alltrees) должен быть помечен, а набор детей, рассмотренных выше, должен быть только соседними немаркированными детьми. Я думаю, нам нужно учитывать случай, когда нет немаркированных детей, но глубинa > 0, это означает, что эта "ветвь" не достигла требуемой глубины и не может составлять часть набора решений (поэтому весь внутренний цикл, связанный с этот кортеж может быть прерван).
Так будет ли это работать? Какие-либо серьезные недостатки? Любой более простой/известный/канонический способ сделать это?
Одна проблема с алгоритмом, описанным выше, заключается в том, что он не удовлетворяет требованию к памяти, так как рекурсия будет содержать большие массивы деревьев в памяти.