Как уменьшить сложность времени?
-
29-09-2020 - |
Вопрос
У меня есть графический генеракодицетагCode и список списков G=(V+E)
, где каждый сублист - подмножество Node
.Я хочу выяснить узлы каждого сублиста, которые не достигаются от других узлов этого сублиста и добавляют кромки между этими узлами.Предположим, генеракодицетагкод= [[1,2,3,4,5,7,8], [9,10], ....] и в сублиста= [1,2,3,4,5,7,8], {1,7,3,8}, достижимый друг от друга и {2,4,5}, достижимых друг от друга, поэтому край необходимо добавить между 1/7/3/8 и 2/4/5.Я использовал следующее:
for each sublist in Node
SG=node_induced_subgraph(sublist) of G
C=connected_components(SG)
for each component c_i in C
add edge between c_i and c_{i+1}
end
end
.
Сложность Node_induced_subgraph () is o (v + e) Сложность подключенных_Components () is o (m + n) # m нет.узлов и n нет.краев в подмахе
Так как уменьшить общую сложность?
Решение
Я собираюсь решить ваш вопрос в двух частях. Во-первых, как обеспечить доступность между узлами в одном «подсублении» с добавлением минимального количества ребер (если вы можете добавить столько ребра, поскольку вы хотите, чтобы вы могли пройти список и подключить один элемент к двум двум соседним элементам - стоимость= «Математический контейнер»> $ o (n) $ операции присоединения к краю, что теоретически самый быстрый метод ...). Если мы хотим добавить как можно меньше ребер, мы только хотят подключить «подключенные компоненты». Я полагаю, что ваш график $ g $ хранится в виде списка смежности.
//reused arrays
visited := bool array of size |V| initialized to false
active := bool array of size |V| initialized to false
//simple dfs
def dfs(node):
if visited[node] or not active[node]: return
visited[node] = true
for child in neighbors(node):
dfs(child)
//algo
def connect_node_list(list):
for node in list: active[node] = true
last := null
for node in list:
if not visited[node]:
dfs(node)
if last != null: add_edge(last,node)
last = node
for node in list:
active[node] = false
visited[node] = false
.
Теперь это Algo имеет время выполнения $ O (n + | E |) $ где $ n $ Это длина генеракодицетагкода. Что ж, честно говоря, это так же, как и ваш Algo, который я просто хочу подчеркнуть, что использование Bool массивов очень желательно в целом; Также я не знаю, как работает ваш «неисправный субграф» - но вы должны избегать создания нового графа.
Теперь идея, которая может быть новой: Вы можете уменьшить количество сублистов, подключив те, которые имеют перекрывающийся элемент. (Конечно, это полезно только в том случае, если они не обязательно отличаются.) Вы можете использовать use-one-struction для этого:
uf := union find structure with |V| elements
for list in sublists:
first = list[0]
for node in list:
uf.unify(first, node)
index := array of length |V|
counter := 0
for element in uf:
index[element] = -1
if uf.parent(element) = element and uf.size(element) > 1:
index[element] = counter
counter++
new_sublists = list of <counter> many lists
for element in uf:
set = uf.find(element)
if index[set] != -1:
new_sublists[index[set]].add(element)
.
Теперь'new_subliest содержит только необходимое количество сублистов (также все сублисты размера 1 удалены). Процедура требует