Algoritmo que encuentra el número de caminos sencillos de a en

34

Puede alguien me sugieren un algoritmo de tiempo lineal que toma como entrada una dirigido acíclico gráfico y dos vértices y y devuelve el número de caminos sencillos de a en . Tengo un algoritmo en el que ejecutaré un DFS (Profund First Search) pero si DFS encuentra entonces no cambiará el color (de blanco a gris) de ninguno de los nodos que vienen en la ruta para que si esta es la subruta de cualquier otra ruta, entonces DFS también vuelve a pasar por esta subruta. Por ejemplo, considere la lista de adyacencia donde necesitamos encontrar el número de rutas de p a v .G=(V,E)ststG
tstpv

poszorsvsrryyvvwzwz
Aquí DFS comenzará con p y luego digamos que va a pz ya que no encuentra v DFS se ejecutará normalmente. la ruta es psryv ya que se encuentra con v , no cambiaremos el color de los vértices s,r,y,v a gris. Luego la ruta pov ya que el color de v todavía es blanco. Luego la ruta posryv ya que el color de s es blanco y de manera similar camino poryvTambién se mantiene un contador que se incrementa cuando se encuentra v .

¿Es correcto mi algoritmo? si no, qué modificaciones son necesarias para corregirlo o cualquier otro enfoque será muy apreciado.

Nota : Aquí he considerado el algoritmo DFS que se proporciona en el libro "Introducción a los algoritmos de Cormen" en el que colorea los nodos de acuerdo con su estado. Por lo tanto, si el nodo no es visitado, inexplorado y explorado, entonces el color será blanco, gris y negro respectivamente. Todas las demás cosas son estándar.

Saurabh
fuente
44
Tenga en cuenta que todas las rutas en un gráfico acíclico dirigido son necesariamente simples (en virtud de la aciclicidad).
Noldorin el

Respuestas:

37

Su implementación actual calculará el número correcto de rutas en un DAG. Sin embargo, al no marcar rutas, tomará un tiempo exponencial. Por ejemplo, en la siguiente ilustración, cada etapa del DAG aumenta el número total de rutas en un múltiplo de 3. Este crecimiento exponencial se puede manejar con programación dinámica.

trozo de cuero

El cálculo de la cantidad de rutas - en un DAG viene dado por la recurrencia, st

Paths(u)={1if u=t(u,v)EPaths(v)otherwise.

Una modificación simple de DFS calculará esto dado como

def dfs(u, t):
    if u == t:
        return 1
    else:
        if not u.npaths:
            # assume sum returns 0 if u has no children
            u.npaths = sum(dfs(c, t) for c in u.children)
        return u.npaths

No es difícil ver que cada borde se mira solo una vez, por lo tanto, un tiempo de ejecución de .O(V+E)

Nicholas Mancuso
fuente
Comprendí su algoritmo y puede hacerse un poco más eficiente mediante el uso de programación dinámica, ya que las mismas llamadas recursivas se llaman muchas veces, por lo que es mejor guardarlas.
Saurabh
1
@SaurabhHota, está utilizando programación dinámica. La primera vez que se encuentra el vértice , calcula el número de caminos que tiene que . Esto se almacena en u.npaths. Cada llamada posterior a no volverá a calcular su número de rutas, sino que simplemente devolverá u.npaths. utu
Nicholas Mancuso
1
Para tales gráficos, ¿no es la respuesta solo m ^ n donde m es el número de nodos en una columna (3 aquí) yn es el número de columnas excluyendo s, t (4 aquí). la salida es 3 ^ 4 = 81 para el gráfico de ejemplo.
saadtaame
@saadtaame, claro; sin embargo, mi intención era simplemente mostrar un aumento exponencial a medida que crece la "longitud" de un gráfico. Por supuesto, para ese gráfico altamente estructurado puede contar en forma cerrada mientras el algoritmo listado funciona para todos los gráficos.
Nicholas Mancuso
3
El tiempo de ejecución supone que puede realizar las adiciones necesarias en tiempo constante, pero los números que se agregan pueden tener bits en el peor de los casos. Si desea el número exacto de rutas, el tiempo de ejecución (contando las operaciones de bits) es en realidad . O(V+E)Θ(V)O(VE)
JeffE
15

Solo necesita notar que la cantidad de rutas desde un nodo al nodo objetivo es la suma de la cantidad de rutas desde sus elementos secundarios hasta el objetivo. Sabes que este algoritmo siempre se detendrá porque tu gráfico no tiene ningún ciclo.

Ahora, si guarda el número de rutas de un nodo al objetivo mientras visita los nodos, la complejidad del tiempo se vuelve lineal en el número de vértices y la memoria lineal en el número de nodos.

molyss
fuente
0

El número de caminos entre dos vértices en un DAG se puede encontrar usando la representación de matriz de adyacencia.

Suponga que A es la matriz de adyacencia de G. Tomando el poder Kth de A después de agregarle la matriz de identidad, le da el número de caminos de longitud <= K.

Dado que la longitud máxima de cualquier ruta simple en un DAG es | V | -1, calcular | V | -1ª potencia daría una cantidad de rutas entre todos los pares de vértices.

El cálculo de | V | -1 th poder se puede hacer haciendo log (| V | -1) multiplicaciones cada uno de TC: | V | ^ 2.

Vivek Anand Sampath
fuente
La pregunta pide un algoritmo de tiempo lineal. Su algoritmo es más lento que eso.
DW
@Vivek, ¿puedes mencionar una referencia para los teoremas en tu respuesta?
Hamideh