Considérons un graphe orienté sur lequel on peut ajouter dynamiquement des bords et faire des requêtes spécifiques.
Exemple: forêt à ensembles disjoints
Considérez l'ensemble de requêtes suivant:
arrow(u, v)
equiv(u, v)
find(u)
le premier ajoute une flèche au graphe, le second décide si u ↔ ∗ v , le dernier trouve un représentant canonique de la classe d'équivalence de ↔ ∗ , soit un r ( u ) tel que u ↔ ∗ v implique r ( v ) = r ( u ) .
Il existe un algorithme bien connu utilisant la structure de données forestières à ensembles disjoints mettant en œuvre ces requêtes en complexité amortie quasi constante, à savoir . Notez que dans ce cas est implémenté en utilisant .equiv
find
Variante plus complexe
Maintenant, je suis intéressé par un problème plus complexe où les directions importent:
arrow(u, v)
confl(u, v)
find(u)
la première ajoute une flèche , la seconde décide s'il y a un nœud w accessible depuis u et v , c'est-à-dire u → ∗ ← ∗ v . Le dernier devrait retourner un objet r ( u ) tel que u → ∗ ← ∗ v implique r ( u ) ∙ r ( v ) où ∙ devrait être facilement calculable. (Pour, disons, calculerconfl
). Le but est de trouver une bonne structure de données telle que ces opérations soient rapides.
Cycles
The graph can contain cycles.
I don't know if there is a way to efficiently and incrementally compute the strongly connected components, in order to only consider DAGs for the main problem.
Of course I would appreciate a solution for DAGs, too. It would correspond to an incremental computation of the least common ancestor.
Naive approach
The disjoint-set forest data structure is not helpful here, since it disregards the direction of the edges. Note that cannot be a single node, in the case the graph is not confluent.
One can define and to define as when . But how to compute this incrementally?
Probably that computing such a big set is not useful, a smaller set should be more interesting, as in the usual union-find algorithm.