Quels sont l'algorithme et la structure de données les plus efficaces pour conserver les informations sur les composants connectés sur un graphique dynamique?

9

Supposons que j'ai un graphe clairsemé fini non orienté et que je dois être capable d'exécuter efficacement les requêtes suivantes:

  • - renvoie T s'il existe un chemin entre N 1 et, sinonIsConnected(N1,N2)TN1 FN2F
  • ConnectedNodes(N) - retourne l'ensemble des nœuds accessibles depuis N

Cela se fait facilement en pré-calculant les composants connectés du graphique. Les deux requêtes peuvent s'exécuter en temps .O(1)

Si je dois également pouvoir ajouter des bords arbitrairement - - alors je peux stocker les composants dans une structure de données à ensembles disjoints . Chaque fois qu'un bord est ajouté, s'il connecte deux nœuds dans des composants différents, je fusionnerais ces composants. Cela ajoute O ( 1 ) à A d e r m a n n ( | N o d e s | ) ) à IAddEdge(N1,N2)O(1) et O ( I n v e r s e A c kAddEdgeO(InverseAckermann(|Nodes|)) et C o n n e c t e d N o d e s (qui pourrait aussi bien être O ( 1 ) ).IsConnectedConnectedNodesO(1)

Si je dois également pouvoir supprimer arbitrairement des bords, quelle est la meilleure structure de données pour gérer cette situation? Est-on connu? Pour résumer, il doit prendre en charge efficacement les opérations suivantes:

  • - rendements T s'il existe un chemin entre N 1 et N 2 , sinon F .IsConnected(N1,N2)TN1N2F
  • - retourne l'ensemble de noeuds qui sont accessibles à partir de N .ConnectedNodes(N)N
  • - ajoute un bord entre deux nœuds. Notez que N 1 , N 2 ou les deux peuvent ne pas avoir existé auparavant.AddEdge(N1,N2)N1N2
  • - supprime un bord existant entre deux nœuds.RemoveEdge(N1,N2)

(Je m'intéresse à cela du point de vue du développement du jeu - ce problème semble se produire dans plusieurs situations. Peut-être que le joueur peut construire des lignes électriques et nous devons savoir si un générateur est connecté à un bâtiment. Peut-être que le joueur peut verrouiller et déverrouiller les portes, et nous devons savoir si un ennemi peut atteindre le joueur. Mais c'est un problème très général, donc je l'ai formulé comme tel)

user253751
la source
ne peut pas être exécuté dans O ( 1 ) , car s'il renvoie une liste deConnectedNodesO(1) noeuds, il faudrait Ω ( n ) fois. Implémentation de C o n n e cnΩ(n) avec un BFS est optimale, donc une structure de données potentielle n'aurait besoin que de prendre en charge IsConnected, AddEdge et RemoveEdge. Cela semble pertinent pour votre question:ConnectedNodesstackoverflow.com/questions/7241151/…
Tom van der Zanden
@TomvanderZanden Renvoyer un ensemble déjà construit (en programmation, un pointeur ou une référence) est ... bien qu'il n'y ait pas grand chose que l'utilisateur de C o n n e c t e d N o d e s puisse faire O ( 1 ) et non couvert par I s C o n n e c t e d . O(1)ConnectedNodesO(1)IsConnected
user253751

Réponses:

11

Ce problème est connu sous le nom de connectivité dynamique et c'est un domaine de recherche actif dans la communauté théorique de l'informatique. Certains problèmes importants sont encore ouverts ici.

Pour clarifier la terminologie, vous demandez une connectivité entièrement dynamique car vous souhaitez ajouter et supprimer des bords. Il y a un résultat de Holm, de Lichtenberg et Thorup (J.ACM 2001) qui atteint le temps de mise à jour et le temps de requête O ( log n / log log n ) . De ma compréhension, il semble être réalisable. Pour parler simplement, la structure des données maintient une hiérarchie d'arbres couvrant - et la connectivité dynamique dans les arbres est plus facile à couvrir. Je peux recommander les notes d' Erik D. Demaine pour une bonne explication voir iciO(log2n)O(logn/loglogn)pour une vidéo. La note d'Erik contient également des pointeurs vers d'autres résultats pertinents. A noter: tous ces résultats sont des résultats théoriques.

Ces structures de données peuvent ne pas fournir de requêtes ConnectedNodes en soi, mais il est facile d'y parvenir. Il suffit de maintenir en tant que structure de données supplémentaire le graphique (disons comme liste de bord doublement connecté) et d'effectuer la recherche en profondeur en premier pour obtenir les nœuds qui peuvent être atteints à partir d'un certain nœud.

A.Schulz
la source