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).
algorithms
graph
Nick ODell
fuente
fuente
Respuestas:
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.
fuente
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)
fuente
"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.fuente