¿Cuál es la intuición de por qué BFS bidireccional es correcto?

Consideremos una generalización de BFS bidireccional, porque la respuesta será más esclarecedora. Normalmente, un BFS bidireccional explora distancias iguales desde cada nodo, pero esto no es necesario para que sea correcto. Considere una versión de BFS bidireccional que además toma una cadena de consejos que es una secuencia de símbolos A y B que le dice en qué orden buscar desde los nodos A y B.

Una cadena de consejos de ABABAB … etc. le dice al algoritmo que busque un nivel desde A, luego un nivel desde B, luego otro nivel desde A (ahora encuentra todos los nodos a una distancia 2 de A), luego un nivel más desde B, y así sucesivamente. Esta cadena de consejos corresponde al BFS bidireccional típico. Una cadena de consejos de AAAAA … correspondería a BFS unidireccional simple de A, y AABAABAAB…. buscaría dos niveles de A para cada nivel de B.

En todos los casos, después de cada nuevo nivel que busca el algoritmo, todos los nodos recién descubiertos se cruzan con el conjunto acumulativo de nodos que alguna vez se descubrieron desde el otro vértice, y si se encuentra una intersección, el algoritmo se detiene e informa la distancia entre origen y destino como el número de símbolos de cadena de consejos procesados ​​hasta ahora (también contando el actual).

Ahora aquí está la afirmación interesante: ¡la corrección del algoritmo es independiente de la cadena de consejos que usa!

Esto es bastante fácil de ver. Si dos nodos están separados por una distancia d, para cuando se procese el símbolo d-ésimo en la cadena de aviso, se han procesado algunos niveles de número k desde A, y se han procesado niveles d-k desde B. Un nodo que se conecta el conjunto de nodos de A y el conjunto de nodos de B definitivamente se encontrarán en este punto, porque si examinamos la ruta más corta (de longitud d) de A a B, veremos que necesariamente debe contener un nodo (es decir , el nodo k + 1-th en la ruta) que es una distancia k de A y una distancia d – k de B.

En otras palabras, no importa qué cadena de consejos tenga, si piensa en la ruta más corta de A a B, está visitando un nodo adicional a lo largo de esa ruta con cada nuevo símbolo en la cadena. Por lo tanto, si la ruta más corta tiene longitud d, se descubrirá a más tardar en el símbolo de cadena de consejos d-ésimo.

Todavía tenemos que argumentar que el nodo de conexión no se descubrirá antes que en el símbolo d-ésimo, pero esto también es fácil. Si se encontrara antes, la suma de distancias exploradas desde A y B sería menor que d. Luego usaríamos el nodo de conexión C y la ruta A -> … -> C -> … -> B como ejemplo de una ruta más corta que d, lo que contradice la hipótesis de que A y B están a una distancia d, por lo que esto puede No suceda

El algoritmo devuelve que los nodos no están conectados si ha explorado todos los nodos desde cualquier punto final y no ha encontrado ningún nodo de conexión con el otro componente conectado. Dado que la mera ausencia de B en el componente conectado de A (o viceversa) es suficiente para garantizar que A y B no estén conectados, esto es correcto.

La intuición principal es que para cualquier camino más corto entre dos vértices, cualquier parte de ese camino es también el camino más corto entre sus extremos: de lo contrario, podríamos reemplazar esta parte con un camino más corto y mejorar todo nuestro camino. Por lo tanto, cualquier prefijo y cualquier sufijo de la ruta óptima también son óptimos. BFS directo mira a través de prefijos óptimos y BFS inverso mira a través de sufijos óptimos.

Si tomamos el vértice exactamente en el medio de una ruta óptima, o uno de los dos vértices en el caso de que la ruta tenga una longitud impar, entonces este vértice estará al frente de las búsquedas desde ambas direcciones después de [math] k [/ math] iteraciones de la ruta óptima tiene una longitud [matemática] 2k [/ matemática] y después de [matemática] k + 1 [/ matemática] iteraciones si la ruta óptima tiene una longitud [matemática] 2k + 1 [/ matemática], porque los vértices a la distancia [ math] l [/ math] de la fuente de BFS regular aparece en el frente después de exactamente [math] l [/ math] iteraciones. La longitud óptima del prefijo / sufijo es [matemática] k [/ matemática] y [matemática] k [/ matemática] en caso de una longitud de ruta completa o [matemática] k [/ matemática] y [matemática] k + 1 [ / math] o [math] k + 1 [/ math] y [math] k [/ math] en el caso de longitud de ruta impar.

No creo que podamos hablar de una “intuición” aquí, porque podríamos probar la corrección y usar un algoritmo, o no podemos. Deberíamos nombrar alguna declaración invariante u otra, y demostrarlo.

Por ejemplo, la invariante principal de Dijkstra se basa en el hecho de que en cada paso tiene el árbol de caminos más cortos desde el vértice actual en un sub-gráfico de vértices, tocado por un algoritmo. Es muy fácil demostrarlo de esa manera.

El hecho invariante de Floyd-Warshall es el hecho de que, después de k iteraciones, tienes los más cortos patrones de todos los vértices a través de los primeros k vértices del gráfico.

Aquí, con la búsqueda bidireccional de BFS, en realidad está utilizando el hecho de la misma manera que en Dijkstra. Por lo tanto, está construyendo las rutas más cortas (donde la ruta es el número de aristas entre ellas) en una sub-gráfica de vértices tocados. Cuando sus 2 “árboles más cortos” se encuentran entre sí en algún vértice, ningún otro vértice recién descubierto podría producir una distancia menor para cada uno de los subgrafos.

También gracias a Michael Levin, su explicación es el lugar aquí también.

More Interesting

¿Por qué char array proporciona String cuando se imprime en el método System.out.println ()?

Si tengo una matriz compuesta de cadenas de dígitos y guiones, ¿cómo puedo usar Javascript para agregar la suma de cada dígito mientras omito los guiones?

¿Qué es la compresión de datos en la base de datos?

¿Son los métodos en algoritmos Java?

¿Cuál es el número esperado de movimientos necesarios para terminar un juego de serpientes y escaleras?

¿Cuál es el método de práctica más eficiente para mejorar las preguntas sobre algoritmos?

Cómo escribir un algoritmo de diccionario en un programa en C

¿Hay algún algoritmo que pueda implementarse en un lenguaje de programación pero no en otro lenguaje de programación?

¿Qué patrones de diseño y algoritmos comunes necesito saber para el desarrollo de Android?

¿Hay alguna estructura de datos que no se pueda representar dentro de una computadora?

Cómo determinar si un conjunto dado se puede dividir en dos subconjuntos o más de modo que la suma de los elementos en esos subconjuntos sea la misma

¿Cómo funciona el algoritmo SCC de Tarjan?

¿A los programadores les gustan las funciones recursivas? ¿Por qué o por qué no?

Tengo una pila masiva de más de 300 pares de calcetines. ¿Cuál es el algoritmo más rápido que puedo usar para extraer unos 25 pares coincidentes de la pila desordenada?

¿Cuáles son algunos algoritmos que usamos diariamente que tienen complejidades [matemáticas] O (n), O (n ^ 2), [/ matemáticas] y [matemáticas] O (\ log n) [/ matemáticas]?