¿Qué algoritmo debo usar para encontrar la ruta más corta en este gráfico?

8

Tengo un gráfico con aproximadamente mil millones de vértices, cada uno de los cuales está conectado a unos 100 otros vértices al azar.

Quiero encontrar la longitud del camino más corto entre dos puntos. No me importa la ruta real utilizada.

Notas:

  • A veces los bordes se cortan o se agregan. Esto sucede aproximadamente 500 veces menos a menudo que las búsquedas. También está bien agrupar cambios de borde si le permite obtener un mejor rendimiento.
  • I puedo pre-procesar el gráfico.
  • Si toma más de 6 pasos, puede regresar con infinito.
  • Es aceptable estar equivocado el 0.01% del tiempo, pero solo al devolver una longitud que es demasiado larga.
  • Todos los bordes tienen una longitud de 1.
  • Todos los bordes son bidireccionales.

Estoy buscando un algoritmo. El psuedocódigo, las descripciones en inglés y el código real son geniales.

Podría usar A *, pero parece optimizado para la búsqueda de rutas.
Pensé en usar el algoritmo de Dijkstra , pero tiene un paso que requiere establecer el atributo encontrado de la ruta más corta de cada vértice al infinito

(Si te estás preguntando sobre el caso de uso, es para el concurso Underhanded C).

Nick ODell
fuente
1
El algo de Dijkstra es A * con h = 0, wrt al 'pathfinding' ¿quiere decir que no tiene forma de estimar un mejor costo mínimo?
jk.
1
Establecer el atributo de ruta más corta encontrada de cada vértice no significa que tenga que escribir 'infinito' mil millones de veces. Solo necesita una función que devuelva 'infinito' cuando no se establece ningún valor.
Kevin Cline

Respuestas:

6

Algoritmo Básico

Mantenga dos conjuntos de nodos a los que pueda llegar desde el nodo inicial y final. De manera alterna, vaya tres pasos desde ambos lados. Cada vez que reemplace su conjunto con nodos, puede alcanzar un paso más. Después de cada paso, verifica los dos conjuntos de nodos comunes.

Optimizaciones

Asegúrese de que puede iterar los conjuntos ordenados para poder buscar nodos comunes en un solo barrido: una operación O (n + m). Las listas serán de hasta un millón de nodos cada una.

Para extender un conjunto con un solo paso, debe consultar todas las conexiones de los nodos en el conjunto original y fusionarlas en un nuevo conjunto ordenado. La fusión de 2 listas ordenadas se puede hacer nuevamente en un solo barrido. Por lo tanto, también debe asegurarse de que puede consultar las conexiones de un nodo según lo ordenado. (Esto podría ser preprocesado).

En los últimos dos pasos, cada nuevo conjunto es el resultado de combinar hasta 10000 de estos resultados de consulta. Es mejor hacer esta fusión adaptativa (fusionar fragmentos de igual tamaño). De esa manera, la estructura de datos del conjunto ordenado puede ser una simple lista vinculada.

De esta manera, todo el algoritmo se convierte en O (6 * n + 6 * n * log n) donde n es max. 1,000,000.

Kris Van Bael
fuente
¿Cómo se verifica la membresía en una lista vinculada en menos de O (n)? Eso parece un gran problema.
Nick ODell el
El truco es recorrer ambas listas simultáneamente. De esa manera, puede verificar si hay dobles en un solo barrido.
Kris Van Bael
¿No será costosa la inserción usando una lista ordenada? Un árbol o hachís funcionaría mejor.
Kevin Cline
Un árbol podría ser mejor. Pero de cualquier manera, la inserción se optimiza al tener todas las conexiones de un nodo previamente ordenadas.
Kris Van Bael
O más bien ... Lista única vinculada está perfectamente bien. Ver ediciones de la respuesta.
Kris Van Bael
2

Solo use la búsqueda de respiración primero (no necesita el alg de Dijkstra porque todos los bordes tienen una longitud uniforme) (y como dijo Kris Van Bael, ejecútelo desde ambos lados)

user470365
fuente
0

"All edges have a length of 1"Este es el mejor de los casos, lo que hace que el Algoritmo de Dijkstra sea una elección de algoritmo codicioso perfecto. Incluso usar el algoritmo de Floyd-Warshall que involucra la multiplicación rápida de matrices funcionaría bien.

Pulposo
fuente
Estoy confundido. Desde el enlace que proporcionó, parece que el algoritmo Floyd-Warshall está dirigido a resolver el problema de la ruta más corta de todos los pares. ¿Es también la mejor manera de encontrar la distancia entre un solo par?
Nick ODell el
@NickODell Floyd-Warshall es un algoritmo codicioso para encontrar los caminos más cortos en un gráfico. Es solo uno, incluido Dijkstra, que es bastante popular, para encontrar rutas más cortas desde el nodo de inicio a todos los demás nodos. Recuerde, está encontrando la ruta más corta desde un nodo designado a todos los demás nodos y no solo dos puntos.
Mushy