Каков наиболее эффективный алгоритм и структура данных для поддержки информации о связанных компонентах на динамическом графе?

9

Скажем, у меня есть неориентированный конечный разреженный граф, и мне нужно эффективно выполнять следующие запросы:

  • IsConnected(N1,N2) - возвращает если есть путь между и N_2 , в противном случае FН 1 Н 2 FTN1N2F
  • ConnectedNodes(N) - возвращает набор узлов, которые доступны из N

Это легко сделать, предварительно вычислив подключенные компоненты графа. Оба запроса могут быть выполнены за O(1) раз.

Если мне также нужно иметь возможность добавлять ребра произвольно - AddEdge(N1,N2) - тогда я могу хранить компоненты в структуре данных с несвязным множеством . Всякий раз, когда добавляется ребро, если оно соединяет два узла в разных компонентах, я бы объединял эти компоненты. Это добавляет стоимость O(1) стоимости AddEdge и O(InverseAckermann(|Nodes|)) к IsConnected и ConnectedNodes (которые также могут быть O(1) ).

Если мне также нужно иметь возможность произвольно удалять ребра, какова лучшая структура данных, чтобы справиться с этой ситуацией? Один известен? Подводя итог, он должен эффективно поддерживать следующие операции:

  • IsConnected(N1,N2) - возвращает T , если существует путь между N1 и N2 , в противном случае F .
  • ConnectedNodes(N) - возвращает набор узлов , которые доступны из N .
  • AddEdge(N1,N2) - добавляет ребро между двумя узлами. Обратите внимание, что N1 , N2 или оба, возможно, не существовали раньше.
  • RemoveEdge(N1,N2) - удаляет существующее ребро между двумя узлами.

(Я заинтересован в этом с точки зрения разработки игры - эта проблема, по-видимому, возникает в довольно многих ситуациях. Возможно, игрок может построить линии электропередачи, и нам нужно знать, подключен ли генератор к зданию. Возможно, игрок может заблокировать и откройте двери, и нам нужно знать, сможет ли враг добраться до игрока. Но это очень общая проблема, поэтому я сформулировал это так)

user253751
источник
O ( 1 ) п П ( п ) С о п п е с т е д Н о д е сConnectedNodes не может работать в , потому что, если он возвращает список из узлов, ему потребуется время . Реализация с BFS является оптимальной, поэтому потенциальная структура данных должна была бы поддерживать только IsConnected, AddEdge и RemoveEdge. Похоже, это относится к вашему вопросу: stackoverflow.com/questions/7241151/…O(1)nΩ(n)ConnectedNodes
Том ван дер Занден
@TomvanderZanden Возвращение уже встроенного набора (в программировании, указателя или ссылки) - это ... хотя пользователь не так много мог бы сделать это и не покрывается . O(1)ConnectedNodesO(1)IsConnected
user253751

Ответы:

11

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

Чтобы прояснить терминологию, вы запрашиваете полностью динамическое соединение, так как хотите добавлять и удалять ребра. Есть результат Хольма, де Лихтенберга и Торупа (J.ACM 2001), который достигает времени обновления и времени запроса . Из моего понимания это кажется осуществимым. Проще говоря, структура данных поддерживает иерархию связующих деревьев, а динамическое связывание в деревьях легче охватить. Я могу порекомендовать заметки Эрика Д. Демейна для хорошего объяснения, смотрите здесь видео. Записка Эрика также содержит указатели на другие соответствующие результаты. Как примечание: все эти результаты являются теоретическими.O(log2n)O(logn/loglogn)

Эти структуры данных могут не предоставлять запросы ConnectedNodes как таковые, но этого легко достичь. Просто поддержите в качестве дополнительной структуры данных график (скажем, как двунаправленный список ребер) и выполните поиск в глубину, чтобы получить узлы, к которым можно обратиться из определенного узла.

A.Schulz
источник