Comment trouver une superstar en temps linéaire?

28

Considérez les graphiques dirigés. Nous appelons un nœud v superstar si et seulement si aucun autre nœud ne peut être atteint à partir de lui, mais tous les autres nœuds ont un bord à v . Officiellement:

v  superstar :⟺outdeg(v)=0indeg(v)=n1

avec n le nombre de nœuds dans le graphique. Par exemple, dans le graphique ci-dessous, le nœud non rempli est une superstar (et les autres nœuds ne le sont pas).

Une superstar
[ source ]

Comment pouvez-vous identifier toutes les superstars dans un graphique dirigé en temps O(n) ? Une représentation graphique appropriée peut être choisie parmi les candidats habituels ; veuillez vous abstenir d'utiliser des représentations qui déplacent la complexité du problème vers le prétraitement.

Aucune hypothèse concernant la densité ne peut être faite. Nous ne supposons pas que le graphique contient une superstar; s'il n'y en a pas, l'algorithme devrait le reconnaître.

Notation : outdeg est le nombre de nœuds sortants d'un noeud, indeg similaire pour les bords entrants.

Raphael
la source
1
Sommes-nous autorisés à O(n+k)k est des arêtes, ou devons-nous regarder uniquement O(1) arêtes sur chaque sommet?
Kevin
@Kevin Non, est une exigence stricte. En ce qui concerne la deuxième question: je ne sais pas si cela est nécessaire, mais vous ne pouvez certainement pas faire plus. O(n)
Raphael
Savez-vous la réponse? Peut-on le faire en ? O(n)
Dave Clarke
@DaveClarke: Oui, et oui.
Raphael
Vous devez restreindre davantage la représentation; un algorithme linéaire est impossible pour une liste d'adjacence (juste pour confirmer qu'un sommet est une superstar, vous devrez peut-être parcourir toute la liste à chaque sommet).
Gilles 'SO- arrête d'être méchant'

Réponses:

18

Nous pouvons éliminer tous les sommets sauf un en vérifiant l'existence de arêtes, car nous pouvons éliminer une possibilité pour chaque arête que nous vérifions. En particulier, s'il y a une arête allant de x à y , nous éliminons x et passons à y (car un autre sommet peut en être atteint); sinon, nous éliminons y (car il ne peut pas être atteint à partir de x ). Une fois que nous atteignons le dernier sommet, celui qui n'est pas éliminé doit être comparé les uns aux autres (assurez-vous que la condition de superstar est maintenue: il y a un bord entrant mais non sortant) jusqu'à ce qu'il soit éliminé ou confirmé comme superstar. Quelques pseudocodes:n1xyxyyx

vertex superstar(graph g)
    current vertex = first
    # Go through each vertex
    for each subsequent vertex in g ("next")
        # If there's an edge from this to the next, we eliminate this one [move to the new one].
        # If not, we just stay here.
        if edge exists from current to next
            candidate = next
        end if
    end for
    # Now we are on the final remaining candidate, check whether it satisfies the requirements.
    # just a rename for clarity
    candidate = current
    for each other vertex in g
        if edge from current to other exists
            return null 
        else if no edge from other to current
            return null
        end if
    end for
    return candidate
end superstar

Passons en revue un exemple pour illustrer la méthode. Prenez ce tableau, avec le sommet source en haut et la destination sur le côté. 1 indique un bord:

12341101210131114110

Je griserai les sommets que nous avons exclus en tant que superstars potentielles. Je vais utiliser le vert et le rouge pour indiquer les bords que nous regardons quand ils le font et ne contiennent pas le bord que nous recherchons, et le bleu pour indiquer où nous avons déjà regardé.

Nous commençons par regarder les sommets 1 et 2.

Le nombre vert indique qu'il y a un bord de 2 à 1, donc nous éliminons 2 et recherchons un bord de 3 à 1 :

12341101210131114110

12341101210131114110-

Nous voyons qu'il n'y a pas un tel bord, donc nous éliminons 1 et prenons 3 comme sommet actuel. Rappelez-vous que nous avons déjà éliminé 2, alors voyez s'il y a un bord de 4 à 3:

12341101210131114110

Il y a une arête de 4 à 3, donc nous en éliminons 4. À ce stade, nous avons éliminé tous les sommets sauf un (3), alors vérifiez ses arêtes et voyez si elle se qualifie:

12341101210131114110

Il y a un bord de 1 à 3 mais pas l'inverse, donc 3 est toujours candidat.

12341101210131114110

Il y a aussi un avantage de 2 à 3 mais pas l'inverse, donc 3 est toujours candidat.

12341101210131114110

Il y a un bord de 4 à 3 mais pas de 3 à 4; cela complète notre vérification des bords de 3 et nous avons constaté qu'il s'agit en fait d'une superstar.

Puisque nous éliminons un sommet comme superstar possible sur chacun des premiers contrôles de bord, le meilleur cas est que le nn1nnn12×(n1)3n3O(n)Θ(n)

Kevin
la source
8

N'est-ce pas le problème des célébrités ?

Il n'y aura qu'une seule superstar (célébrité) s'il y en a une.

A[i,j]=1ij0

A[i,j]O(1)A[i,j]=1iA[i,j]=0j

Tenir une liste des candidats actuels, en les éliminant un par un. Une liste chaînée devrait suffire.

À la fin, vous pouvez vérifier si votre candidat est bien une superstar.

O(n)

Aryabhata
la source
(i,j)
3
@Raphael: Choisissez simplement les deux premiers candidats de la liste chaînée. (tête et tête-> suivant).
Aryabhata
6

Cette réponse concerne la version de la question où toute représentation graphique était possible, et non la version actuelle de la question.

  • Stockez votre graphique sous la forme d'une paire de listes de contiguïté et de liste de contiguïté inversée, où chaque liste contient en plus la longueur de la liste, d'où le nombre de bords extérieur et intérieur, respectivement.

  • Prétraitement: calcul de la liste de contiguïté inverse (c'est-à-dire la liste des entrées). CoûtO(|E|)

  • 0n1O(|N|)

Dave Clarke
la source
Ok, je vois que permettre une représentation graphique est trop faible. J'ai limité la question à ce que je voulais.
Raphael
2

Juste pour référence, c'est le pseudocode d'une version récursive de ce que Kevin a posté.

superstar(V, E) {
  if ( |V| == 1 ) {
    return V.pop
  }

  a = V.pop
  b = V.pop
  if ( (a,b) ∈ E ) {
    no_ss = a
    keep  = b
  }
  else {
    no_ss = b
    keep = a
  }

  s = superstar(V ++ keep)

  return ( s != null && (no_ss, s) ∈ E && !(s, no_ss) ∈ E ) ? s : null
}

hasSuperstar(V, E) = superstar(V, E) != null
Raphael
la source