¿Cómo verifico si un gráfico dirigido es acíclico? ¿Y cómo se llama el algoritmo? Agradecería una referencia.
82
¿Cómo verifico si un gráfico dirigido es acíclico? ¿Y cómo se llama el algoritmo? Agradecería una referencia.
Respuestas:
Intentaría ordenar el gráfico topológicamente , y si no puedes, entonces tiene ciclos.
fuente
Hacer una búsqueda simple en profundidad no es suficiente para encontrar un ciclo. Es posible visitar un nodo varias veces en un DFS sin que exista un ciclo. Dependiendo de dónde empiece, es posible que tampoco visite el gráfico completo.
Puede comprobar los ciclos en un componente conectado de un gráfico de la siguiente manera. Encuentre un nodo que solo tenga bordes salientes. Si no existe tal nodo, entonces hay un ciclo. Inicie un DFS en ese nodo. Al atravesar cada borde, verifique si el borde apunta hacia un nodo que ya está en su pila. Esto indica la existencia de un ciclo. Si no encuentra tal borde, no hay ciclos en ese componente conectado.
Como señala Rutger Prins, si su gráfico no está conectado, debe repetir la búsqueda en cada componente conectado.
Como referencia, el algoritmo de componentes fuertemente conectado de Tarjan está estrechamente relacionado. También le ayudará a encontrar los ciclos, no solo a informar si existen.
fuente
El lema 22.11 del libro
Introduction to Algorithms
(segunda edición) establece que:fuente
Solución 1 : algoritmo de Kahn para comprobar el ciclo . Idea principal: mantener una cola donde el nodo con cero grados se agregará a la cola. Luego despegue los nodos uno por uno hasta que la cola esté vacía. Compruebe si existen bordes internos de algún nodo.
Solución 2 : algoritmo de Tarjan para comprobar el componente conectado fuerte.
Solución 3 : DFS . Utilice una matriz de enteros para etiquetar el estado actual del nodo: es decir, 0 - significa que este nodo no ha sido visitado antes. -1: significa que este nodo ha sido visitado y sus nodos secundarios están siendo visitados. 1: significa que este nodo ha sido visitado y está hecho. Entonces, si el estado de un nodo es -1 mientras realiza DFS, significa que debe haber existido un ciclo.
fuente
La solución proporcionada por ShuggyCoUk está incompleta porque es posible que no verifique todos los nodos.
Esto tiene complejidad de tiempo O (n + m) u O (n ^ 2)
fuente
m = O(n^2)
ya que el gráfico completo tiene exactamentem=n^2
bordes. Entonces eso esO(n+m) = O(n + n^2) = O(n^2)
.Sé que este es un tema antiguo, pero para los futuros buscadores, aquí hay una implementación de C # que creé (¡no hay afirmación de que sea más eficiente!). Está diseñado para utilizar un número entero simple para identificar cada nodo. Puede decorarlo como desee, siempre que su objeto de nodo tenga valores hash e iguales correctamente.
Para gráficos muy profundos, esto puede tener una sobrecarga alta, ya que crea un conjunto de hash en cada nodo en profundidad (se destruyen en el ancho).
Ingresa el nodo desde el que desea buscar y la ruta a ese nodo.
Al verificar ciclos debajo de cualquier nodo, simplemente pase ese nodo junto con un hashset vacío
fuente
No debe haber ningún borde posterior mientras realiza DFS. Mantenga un registro de los nodos ya visitados mientras realiza DFS, si encuentra un borde entre el nodo actual y el nodo existente, entonces el gráfico tiene un ciclo.
fuente
aquí hay un código rápido para encontrar si un gráfico tiene ciclos:
La idea es así: un algoritmo dfs normal con una matriz para realizar un seguimiento de los nodos visitados, y una matriz adicional que sirve como marcador para los nodos que condujeron al nodo actual, de modo que siempre que ejecutemos una dfs para un nodo establecemos su elemento correspondiente en la matriz de marcadores como verdadero, de modo que siempre que se encuentre un nodo ya visitado, verifiquemos si su elemento correspondiente en la matriz de marcadores es verdadero, si es verdadero, entonces es uno de los nodos que se permite a sí mismo (por lo tanto, un ciclo), y el truco es que cada vez que un dfs de un nodo regresa, volvemos a establecer su marcador correspondiente en falso, de modo que si lo visitamos nuevamente desde otra ruta no nos engañemos.
fuente
Acabo de tener esta pregunta en una entrevista de Google.
Orden topológico
Puede intentar ordenar topológicamente, que es O (V + E) donde V es el número de vértices y E es el número de aristas. Un gráfico dirigido es acíclico si y solo si esto se puede hacer.
Eliminación recursiva de hojas
Elimina de forma recursiva los nodos hoja hasta que no quede ninguno, y si queda más de un nodo, tienes un ciclo. A menos que me equivoque, esto es O (V ^ 2 + VE).
Estilo DFS ~ O (n + m)
Sin embargo, un algoritmo eficiente al estilo DFS, el peor de los casos O (V + E), es:
fuente
Aquí está mi implementación ruby del algoritmo de nodo peel off leaf .
fuente
Puede usar la inversión del ciclo de búsqueda de mi respuesta aquí https://stackoverflow.com/a/60196714/1763149
def is_acyclic(graph): return not has_cycle(graph)
fuente