¿Cómo no es aplicable el algoritmo de Dijkstra a los gráficos con pesos negativos? ¿No podemos simplemente agregar alguna constante a cada peso para que cada peso sea positivo, y luego aplicar el algoritmo de Dijkstra para encontrar el camino más corto?

Tu primera pregunta ¿Por qué Dijkstra no es aplicable en gráficos de borde negativo?

Al ser un algoritmo codicioso, el algoritmo de Dijkstra no se puede aplicar en gráficos con pesos de borde -ve.

Razón :

“En el algoritmo de Dijkstra, tenemos una cola prioritaria de vértices. En cada paso hacemos estallar el vértice cuya distancia desde la fuente es menor con la ayuda de la cola de prioridad (min). Luego, el vértice revelado actualiza la distancia de la fuente de todos los demás nodos. el paso se repite hasta que todos los vértices se destapen

Dejando los detalles sangrientos. La respuesta a su pregunta se encuentra simplemente aquí:

¿Por qué sacamos el vértice de menor distancia de la cola Prioridad?

Tomemos el nodo / vértice emergente como P, y su distancia de la Fuente como D (p). Ahora, la razón por la cual P aparece, es que D (p) no puede ser ‘RELAJADO’ más por ningún vértice de la competencia. Por RELAJADO me refiero al código de actualización trillado:

Para cada vecino si D (p) <D (n) + Edge (n, p)

Entonces D (p) = D (n) + Edge (n, p)

donde n es vecino de p.

Como todos los bordes son + ve, entonces D (n) tiene que ser positivo. Edge (n, p) es obviamente positivo. Por lo tanto, D (p) no puede ser actualizado / RELAJADO por ningún otro vecino porque D (p) es el menos entre todos los D’s. Por lo tanto, D (n)> D (p), y debido a que Dijkstra se aplica en + cinco bordes ponderados, D (n) + Edge (n, p)> D (p). Por lo tanto, con seguridad, sacamos P. Debido a que está presente, D (p) está a la menor distancia de la fuente y ningún otro nodo tiene el poder de hacerlo más bajo. Período.”

Esta suposición falla horriblemente si los pesos de borde son negativos. Un vértice salido de la cola de prioridad puede ser reducido aún más por algún nodo si se permite que los pesos de borde sean negativos. Si D (p) <D (n), pero no podemos decir que

D (p) <D (n) + Edge (n, p), porque Edge (n, p) puede ser negativo ahora. Por lo tanto, no podemos simplemente reventar el vértice, con la menor distancia desde la fuente ahora.

Esta es la forma más fácil de entender la codicia de Dijkstra, sin pasar por las pruebas matemáticas adecuadas, que de todos modos se inspiran en esta teoría.

Su segunda pregunta ¿Qué hay de agregar un peso constante en cada borde, para que todos sean positivos y luego aplicar Dijkstra?

Para responder a esto, todo lo que necesita hacer es sentarse y dibujar un gráfico y ver dónde irá mal. De todos modos, te ahorraré el esfuerzo al negar tu argumento con un simple ejemplo. Deje que solo haya dos caminos desde el nodo S a un nodo T-

  1. S – (+1) -> A – (+2) -> B – (-1) -> C – (+2) -> D – (+1) -> T.

   2. S – (+5) -> P – (+2) -> T.

donde S es la fuente.

Ahora,

D (T) por ruta 1 = 1 + 2-1 + 2 + 1 = 5.

D (T) por la ruta 2 = 5 + 2 = 7.

Por lo tanto, D (T) debe ser 5 a través de la ruta 1 por cualquier algoritmo correcto de ruta más corta.

Ahora aplica tu sugerencia de agregar un peso constante para que todos los bordes no sean negativos. Vamos a agregar 1 a todos los bordes. Nuevos caminos:

  1. S – (+2) -> A – (+3) -> B – (0) -> C – (+3) -> D – (+2) -> T.

   2. S – (+6) -> P – (+3) -> T.

Ahora,

D (T) por ruta 1 = 2 + 3 + 0 + 3 + 2 = 10

D (T) por la ruta 2 = 6 + 3 = 9.

Ahora D (T) = 9 a través de la ruta 2 ?? Incluso si realiza un seguimiento de los bordes y resta el peso constante al final. Has tomado un camino equivocado, amigo mío.

Entonces, ¿cuál fue el defecto?

Agregar un peso constante puede hacer que su gráfico sea positivo, pero ignora el número de bordes en el camino a través del cual asignará distancias desde la fuente. Para una ruta de borde numerada larga, agrega más peso constante y agrega menos a una ruta de borde numerada más corta. ¡Por lo tanto, su parcialidad hacia caminos de borde numerados más cortos es la VELA!

No puedes.
Para dar un ejemplo simple.

Sea S el vértice fuente.
Sea T el vértice de destino.
Consideramos dos rutas de S a T-ruta A y ruta B.
Camino A
S -1-> X-1-> Y – (- 3) -> T
aquí los pesos de borde son
SX = 1
XY = 1
y YT = -3
Camino b
S -1-> T
aquí los pesos de borde son
ST = 1

Ahora digamos que agrega x a cada peso de borde.
Entonces, para la ruta A, agrega un total de 3x peso y para la ruta B agrega un total de x peso.

Dado que, en el caso original PathA cual es
(1 + x) + (1 + x) + (- 3 + x) <1 + x
resolviendo lo que obtienes
x <1
Esto significa que para cualquier x> = 1 , el invariante no se mantendría.
Pero, x <1 significa que el borde YT = -3 + x siempre permanecerá negativo.

Por lo tanto, incluso después de agregar los pesos positivos que satisfacen a los invariantes, YT sigue siendo negativo. Si elige cualquier otro peso positivo, cambia el gráfico por completo.

El algoritmo de Dijkstra no puede funcionar con borde negativo. Además, no podemos agregar trivialmente una constante a cada uno de los pesos de los bordes y hacer que no sean negativos para continuar.

¿Por qué el algoritmo de Dijkstra no funciona con borde negativo?

En la figura anterior, estamos tratando de obtener las rutas más cortas desde el nodo fuente 1 a todos los demás nodos (nodo 2 y nodo 3). Dado que el algoritmo de Dijkstra funciona empleando un proceso codicioso, genera 20 como el costo de ruta más corto para el nodo 2.

Como podemos ver, desde el nodo 1, podemos ir a dos nodos: el nodo 2 y el nodo 3, a un costo de 20 y 40 respectivamente. Por lo tanto, ir al nodo 2 es más barato. Y es por eso que genera 20 para ser el costo más barato para llegar al nodo 2.

Sin embargo, sabemos que el costo más barato para alcanzar el nodo 2 es a través del nodo 3. Y el costo asociado es: 40 + (-30) = 10. Entonces, el algoritmo de Dijkstra se equivoca. Se equivoca porque no puede prever que más tarde, una ventaja negativa puede reducir el costo total a menos de 20.

Si observamos cuidadosamente, vemos que el cálculo incorrecto por el algoritmo de Dijkstra ocurre debido al borde negativo. Si el costo del nodo 3 al nodo 2 no hubiera sido un valor negativo, nunca podría reducir el costo total a menos de 20, después de ser agregado a 40.

¿Por qué no agrega un costo constante a cada borde?

Ahora que nos damos cuenta, el algoritmo de Dijkstra falla debido al borde negativo del nodo 3 al nodo 2, que tiene el valor -30, podríamos sentir la tentación de agregar 30 a cada uno de los bordes. Podríamos pensar, de esta manera podemos eliminar el borde negativo. Y hacerlo sería justo; después de todo, estamos agregando el mismo valor a cada uno de los bordes. Hagámoslo y veamos qué pasa.

Después de actualizar los costos de borde, el gráfico se ve como se muestra arriba. Entonces, ¿cuál es la ruta más barata desde el nodo 1 al nodo 3 ahora?

Bueno, ahora el costo más barato es 50, que usa el borde directo del nodo 1 al nodo 2. Pero se supone que esta no es la ruta más barata, ¿verdad? La ruta más barata era el nodo 1 -> nodo 3 -> nodo 2 , antes de ajustar el costo del borde. El ajuste del costo del borde no debería cambiar el gráfico. No debe cambiar el camino más barato, ¿verdad?

Entonces, ¿por qué sucede eso? Bueno, si observamos, encontramos que la ruta nodo 1 -> nodo 3 -> nodo 2 usa dos bordes / segmentos – nodo 1 al nodo 3 y nodo 3 al nodo 2. Por otro lado, ruta nodo 1 -> nodo 2 usa solo un borde / segmento. La forma en que hemos actualizado el costo de borde, agregando una constante a cada segmento de ruta, no es justo para una ruta que usa más segmentos de ruta. Para la ruta que usa dos segmentos de ruta, que originalmente era la ruta más barata, hemos agregado la constante 30 dos veces. Por otro lado, para la ruta que usa solo un segmento de ruta, hemos agregado 30 solo una vez. De esa manera, somos injustos con la ruta que utiliza más segmentos de ruta.

Debemos agregar una constante a cada una de las rutas, no a cada uno de los segmentos de ruta.

Solución

El algoritmo de Johnson hace esto: agrega un costo constante a cada ruta con una determinada fuente s a un determinado objetivo t. Lo hace, al encontrar un conjunto especial de valores de desplazamiento para eliminar los bordes negativos de un gráfico. Una vez hecho esto, el algoritmo de Dijkstra puede funcionar. Pero eso funciona en ausencia de un ciclo negativo en el gráfico.

Esto es de mi publicación El problema de Dijkstra con borde negativo en mi blog Compartiendo experiencias ( gopalcdas dot com ).

Los pesos negativos del borde, prácticamente, no tienen sentido. Por ejemplo, si la suma de todos los bordes en un ciclo en un gráfico es negativa, puede pasar por ese ciclo una y otra vez para reducir el costo. Este ciclo nunca terminará porque cada vez que se reduce su costo. Entonces, la primera suposición implica que los pesos de borde son positivos.

Agregar un valor constante a todos los bordes lo convertiría en un problema diferente porque si hay caminos con diferente número de bordes y agregamos un valor constante a cada borde, entonces un borde se incrementaría en una cantidad mayor (el que tiene más bordes) y esto no dará como resultado una solución óptima.

More Interesting

¿Cuánto tiempo te lleva programar un algoritmo razonablemente complicado?

¿Desde dónde debemos comenzar a aprender IA, aprendizaje automático y algoritmos?

¿Cuál es el mejor algoritmo de búsqueda en programación?

¿Qué nivel de matemática se requiere para el libro "Introducción a los algoritmos 3ra edición" (MIT Press)?

Noto que las estructuras de datos son difíciles de entender y asimilar con solo leerlas. ¿Qué tengo que hacer?

Cómo resolver este problema DP (http://codeforces.com/gym/101061/problem/F)

Si la compresión sin pérdida es completamente reversible, ¿por qué no omitimos un paso y solo usamos los archivos en su estado comprimido?

Cómo calcular dos nodos distantes mínimos a partir de dos conjuntos de nodos en un gráfico

¿Cómo funciona un algoritmo de bogosort cuántico?

¿Cuánta codificación necesito saber antes de comenzar con los algoritmos?

¿Alguien puede aprender las ideas asociadas con los algoritmos sin aprender a codificar primero?

Un k-palíndromo es una cadena que se transforma en un palíndromo al eliminar como máximo k caracteres de él. Dada una cadena S y un número entero K, ¿encuentra si S es un k-palíndromo o no? Restricciones: S tiene como máximo 20,000 caracteres y 0 <= k <= 30

Cómo garantizar un resultado devuelto de la función que llamamos (en sí mismo) es correcto en la recursividad

¿Cuáles son algunas diferencias entre los campos de la investigación algorítmica y la investigación de operaciones?

¿Cuáles son algunos algoritmos que todo programador debe aprender / saber?