¿Cómo encontrar una superestrella en tiempo lineal?

28

Considere gráficos dirigidos. Llamamos a un nodo v superestrella si y solo si no se puede alcanzar a otro nodo desde él, pero todos los demás nodos tienen una ventaja para . Formalmente:v

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

con el número de nodos en el gráfico. Por ejemplo, en el gráfico a continuación, el nodo sin llenar es una superestrella (y los otros nodos no lo son).norte

Una superestrella
[ fuente ]

¿Cómo puede identificar todas las superestrellas en gráficos dirigidos en tiempo ? Se puede elegir una representación gráfica adecuada de los candidatos habituales ; absténgase de utilizar representaciones que trasladen la complejidad del problema al preprocesamiento.O(norte)

No se pueden hacer suposiciones con respecto a la densidad. No asumimos que el gráfico contiene una superestrella; Si no hay ninguno, el algoritmo debería reconocerlo.

Notación : es el número de bordes salientes de un nodo, similar para los bordes entrantes.otutremisolyonorteremisol

Rafael
fuente
1
¿Se nos permite donde k es bordes, o necesitamos mirar solo O ( 1 ) bordes en cada vértice? O(norte+k)kO(1)
Kevin
@ Kevin No, es un requisito estricto. Con respecto a la segunda pregunta: no sé si eso es necesario, pero ciertamente no puedes hacer más. O(norte)
Raphael
¿Sabes la respuesta? ¿Se puede hacer en ? O(norte)
Dave Clarke
@DaveClarke: Sí, y sí.
Raphael
Debe restringir aún más la representación; un algoritmo lineal es imposible para una lista de adyacencia (solo para confirmar que un vértice es una superestrella, es posible que deba revisar toda la lista en cada vértice).
Gilles 'SO- deja de ser malvado'

Respuestas:

18

Podemos eliminar todos los vértices menos uno verificando la existencia de aristas porque podemos eliminar una posibilidad para cada arista que verificamos. En particular, si hay un borde que va de x a y , eliminamos x y avanzamos hacia y (ya que se puede alcanzar otro vértice desde él); si no, eliminamos y (ya que no se puede alcanzar desde x ). Una vez que alcanzamos el último vértice, el vértice que no se elimine debe compararse entre sí (asegúrese de que se cumpla la condición de superestrella: hay un borde entrante pero no saliente) hasta que se elimine o confirme como superestrella. Algunos pseudocódigo: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

Veamos un ejemplo para ilustrar el método. Tome esta matriz, con el vértice de origen en la parte superior y el destino al lado. 1 indica un borde:

12341101210131114110

Eliminaré los vértices que hemos descartado como posibles superestrellas. Usaré verde y rojo para indicar los bordes que estamos viendo cuando lo hacen y no contienen el borde que estamos buscando, y azul para indicar dónde ya hemos buscado.

Comenzamos mirando los vértices 1 y 2.

El número verde muestra que hay un borde de 2 a 1, por lo que eliminamos 2 y buscamos un borde de 3 a 1 :

12341101210131114110

12341101210131114110

Vemos que no existe tal borde, por lo que eliminamos 1 y tomamos 3 como nuestro vértice actual. Recuerde que ya hemos eliminado 2, así que vea si hay una ventaja de 4 a 3:

12341101210131114110

Hay un borde de 4 a 3, por lo que eliminamos 4. En este punto, hemos eliminado todos menos uno de los vértices (3), así que revise sus bordes y vea si califica:

12341101210131114110

Hay una ventaja de 1 a 3 pero no la inversa, por lo que 3 sigue siendo un candidato.

12341101210131114110

También hay una ventaja de 2 a 3, pero no al revés, por lo que 3 sigue siendo un candidato.

12341101210131114110

Hay una ventaja de 4 a 3 pero no de 3 a 4; eso completa nuestra comprobación de los bordes de 3 y hemos descubierto que, de hecho, es una superestrella.

n1nnn12×(n1)3n3O(n)Θ(n)

Kevin
fuente
8

¿No es este el problema de las celebridades ?

Solo habrá una superestrella (celebridad) si hay una.

Utilizamos la representación de matriz de adyacencia, donde UNA[yo,j]=1 si hay un borde dirigido desde yo a jde lo contrario es 0 0. (Supongo que está permitido).

Al mirar UNA[yo,j] (se puede hacer en O(1) tiempo) podemos eliminar al menos uno de ellos como candidato para ser la celebridad: si UNA[yo,j]=1, entonces puedes eliminar yo. SiUNA[yo,j]=0 0 podemos eliminar j.

Mantener una lista de candidatos actuales, eliminando uno por uno. Una lista vinculada debería ser suficiente.

Al final, puede verificar si su candidato es realmente una superestrella.

Este algoritmo será O(norte).

Aryabhata
fuente
¿Cómo eliges adecuado (yo,j)en tiempo constante?
Raphael
3
@Raphael: simplemente elija los dos primeros candidatos de la lista vinculada. (cabeza y cabeza-> siguiente).
Aryabhata
6

Esta respuesta aborda la versión de la pregunta donde era posible cualquier representación gráfica, no la versión actual de la pregunta.

  • Almacene su gráfico como un par de lista de adyacencia y lista de adyacencia inversa, donde cada lista contiene además la longitud de la lista, por lo tanto, el número fuera y dentro de los bordes, respectivamente.

  • Preprocesamiento: calcular la lista de adyacencia inversa (es decir, la lista de bordes). CostoO(El |miEl |).

  • Recorre las listas y selecciona cualquier nodo donde esté el número de bordes externos 0 0 y el número de bordes es norte-1. CostoO(El |norteEl |).

Dave Clarke
fuente
Ok, veo que permitir cualquier representación gráfica es demasiado débil. Limité la pregunta a lo que pretendía.
Raphael
2

Solo como referencia, este es un seudocódigo de una versión recursiva de lo que Kevin publicó.

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
Rafael
fuente