Está en la página 1de 7

Estructura de Datos y Algoritmos II (EDA II) curso 2019-2020

Conferencia # 05: “Algoritmos para la búsqueda de caminos mínimos en grafos ponderados con
costos negativos.
Algoritmo de Bellman-Ford para obtener caminos mínimos con pesos negativos.
Seudocódigo

RECORDAR
La longitud de un camino con pesos es la suma del costo de las aristas del camino. En el problema de
los caminos mínimos con pesos positivos, las aristas tienen costos no negativos. Queremos calcular los
caminos mínimos desde un vértice origen al resto de los vértices.
Como algoritmos para la búsqueda de caminos mínimos en grafos ponderados se estudian varios
métodos, dentro de ellos:
a) Búsqueda de caminos mínimos en grafos ponderados con pesos negativos, conocido como
algoritmo de Bellman-Ford, que estudiaremos en la actividad de hoy.

Problema del camino mínimo con costos negativos.

PROBLEMA DE LOS CAMINOS MÍNIMOS CON COSTOS NEGATIVOS Y ÚNICO


ORIGEN. Buscar el camino más corto (medido con su costo total) desde el vértice O al resto de
los vértices.
Los costos de las aristas pueden ser negativos.

El algoritmo de Dijkstra necesita que los costos de las aristas sean positivos. Esto es razonable para la
mayoría de las aplicaciones, pero en ocasiones es demasiado restrictivo. Por ejemplo, el siguiente es un
grafo que tiene aristas negativas y debiéramos disponer de un algoritmo que nos permita calcular sus
caminos mínimos, pues, como se aprecia a simple vista, estos existen:

1
V V
0 1 3
-3
2
V
V 2 3
2

Supongamos V0 el vértice inicial. Calculamos su distancia igual a 0 y lo introducimos en la cola de prioridad:


0
1
V V
0 1 3
-3
0
2
V
V 2 3
2

Sacamos el V0. Desde él visitamos el vértice V1 con distancia 1 y el vértice V2 con distancia 2.

1
0 1
1
V V
0 1 3
-3
1 2
2
V
V 2 3
2
2

Desde V1 visitamos V3 con distancia 4

0 1
1
V V
0 1 3
-3
4
2 3
2
V
V 2 3
2
2

Sacamos el vértice V2; desde él podemos visitar el V1, que ya tiene distancia marcada diferente a INFINITO y el
algoritmo de Dijkstra no nos deja; pero como sabemos que hay aristas con costo negativo, que disminuyen cualquier valor
al que se le sume, debemos permitir que se pueda visitar el nodo V1. Visitamos nuevamente el V1, ahora su distancia es
-1 y lo llevamos a la cola. Desde V2 se puede acceder al V3, pero no se disminuye su distancia.
0 -1
1
V V
0 1 3
-3
4
3 1
2
V
V 2 3
2
2

Extraemos ahora el vértice V3 que no tiene adyacentes.

0 -1
1
V V
0 1 3
-3
2
1
2
V
V 2 3
2
2

Se extrae el V1 y se disminuye la distancia de V3 a 2 y se pone nuevamente en la cola.

2
0 -1
1
V V
0 1 3
-3
2
3
2
V
V 2 3
2
2

Se extrae nuevamente el V3 que no tiene adyacentes. La cola queda vacía y se termina.


0 -1
1
V V
0 1 3
-3
2
2
V
V 2 3
2
2

Este ejemplo nos dice que necesitamos un algoritmo que permita aristas de costo negativo y que posibilite el análisis de
aquellos vértices que ya han sido marcados como visitados, pues su distancia pudiera disminuir.
Analicemos este otro ejemplo:
2
V V
0 1 4
1
-4
V
V 2 3
2
El recorrido V0, V1, V2, V0 tendrá un costo: 2+1+(-4) = -1. Es decir, se mejora el costo inicial 0 del V0; pero si
visitamos nuevamente el V1, el costo también se disminuye y, así sucesivamente, cada vez que pasemos por uno de estos
vértices el costo se disminuirá en -1 (el costo total del ciclo). Resulta claro que, en este grafo no existen caminos mínimos
desde el vértice V0.

El bucle V0, V1, V2, V0 se denomina ciclo de costo negativo; cuando existe uno en un grafo, algunos caminos mínimos
no están definidos. Las aristas de costo mínimo no son malas por sí mismas, son los ciclos los que lo son.
El algoritmo que vamos a estudiar encontrará los caminos mínimos o hará notar la existencia de ciclos con costo
negativo. Se utiliza una cola, como en el algoritmo sin pesos, y se usa Dv + Cv,w como medida de la distancia, como en
el algoritmo de Dijkstra.
Cuando se visita el vértice v por i-ésima vez, el valor de Dv es la longitud del camino más corto formado por, a lo sumo, i
aristas. En un grafo con N vértices, que no tenga ciclo de costo negativo, un vértice solamente podrá ser visitado N-1
veces.
Vamos a utilizar la variable extra para conocer si un vértice está o no en la cola y las veces que ha salido de ella. Para
ello:
 cuando se añade el vértice a la cola, se incrementa extra.
 cuando se quita de la cola, lo incrementamos de nuevo.
Por tanto, en el momento que el campo extra de un vértice tome un valor mayor a 2*N, eso significa que ya ha sido
visitado más de N veces o, lo que es equivalente, estamos en presencia de un ciclo de costo negativo.
Observe que:
 los vértices que están en la cola siempre tendrán en extra un valor impar,
 los que no han entrado tienen valor 0
 los que han entrado y salido, tendrán valor par.

3
Cuando se cambia la distancia de v a algún w, pero ya está en la cola (porque extra es impar), no lo añadiremos de
nuevo, sino que le sumamos 2 para indicar que podría haber salido y entrado a la cola; esto se hace con el objetivo de
acelerar el algoritmo en presencia de ciclos negativos.

Analicemos el algoritmo mediante el ejemplo:


2
V V
0 1 4
1
-4
V
V 2 3
2

Supongamos a V0 como vértice origen. Observe que, V0, V1, V2, V0 forman un ciclo de costo negativo. Nuestro
algoritmo debe ser capaz de detectarlo.
Aplicamos limpiarDatos() , actualizamos el valor de tabla [0].dist = 0, colocamos a V0 en la cola e
incrementamos su campo extra en 1.
Tenemos, entonces:
0
2
V V
0 1 4
1 1
-4
V
V 2 3
2

Cola
0

Sacamos de la cola el vértice V0, incrementamos su valor de extra (ahora es 2); desde éste se puede visitar el V1. Le
calculamos su distancia (2), le indicamos que V0 es su antecesor, le incrementamos el valor de extra y lo incluimos en
la cola.

0 2
2
V V
0 1 4
2 1 1

-4
V
V 2 3
2

Sacamos de la cola el vértice V1, incrementamos su valor de extra (ahora es 2); desde este se pueden visitar V3 y V2.
Calculamos la distancia a V3 (6), le indicamos que V1 es su antecesor, le incrementamos el valor de extra y lo
incluimos en la cola. Hacemos lo mismo con V2. Nos queda entonces:

4
0 2
2
V V
0 1 4
2 1 2 6
-4
V
V 2 3
3 2 1
1

3 2
Sacamos de la cola a V3, le incrementamos su campo extra en 1. Desde él no podemos visitar ningún nodo.
Sacamos de la cola a V2, le incrementamos su campo extra en 1. Desde él podemos visitar a V0 y a V3.
0 2
2
V V
0 1 4
2 1 2 6
-4
V
V 2 3
3 2 2
2

La distancia a V0 se puede mejorar, la marcamos en -1; ahora le antecede el V2, le incrementamos el campo extra
(ahora es 3) y lo colocamos en la cola. La distancia a V3 también disminuye, ahora es 5, le indicamos que lo antecede el
V2, le incrementamos el extra (3) y lo colocamos en la cola.
-1 2
2
V V
0 1 4
3 1 2 5
-4
V
V 2 3
3 2 3
2

0 3

Sacamos de la cola a V0, le incrementamos extra (4). Visitamos el vértice V1, su distancia disminuye a 1, le
incrementamos extra (3) y lo colocamos en la cola.
-1 1
2
V V
0 1 4
4 1 3 5
-4
V
V 2 3
3 2 3
2

3 1

5
Sacamos de la cola a V3, se incrementa extra a 4. Desde él no se visita ningún nodo. Sacamos a V1, su extra vale
ahora 4. Desde él visitamos el V2 y el V3.
-1 1
2
V V
0 1 4
4 1 4 5
-4
V
V 2 3
3 2 4
2

La distancia a V2 disminuye, ahora es 2, e incrementamos extra (3) y lo colocamos en la cola. La distancia a V3 se


mantiene igual.
-1 1
2
V V
0 1 4
4 1 4 5
-4
V
V 2 3
2 2 4
3

2
Observe que desde V2 se disminuirá el valor de la distancia a V0; de este a V1; de este a V2 nuevamente, y así
sucesivamente. Los vértices V0, V1 y V2 estarán entrando y saliendo a la cola. Chequeando el valor que alcanza el
campo extra , podemos detener el algoritmo en el momento que alguno rebase el doble de la cantidad de vértices.

o Seudocódigo.

/**
* Ejecuta el algoritmo de caminos mínimos. Se permiten aristas con costo negativo.
* Devuelve false si se detectan ciclos de costo negativos.
*/
Dado un vértice inicial s:
1. 1-Se inicializan todos los atributos necesarios a través del método
limpiarDatos ().
2. 2-Se actualiza la distancia de s en cero.
3. Se pone a s en la cola
4. Se aumenta el atributo extra de s
5. Mientras la cola No este vacía:
Se quita el primero de la cola (v)
Se aumenta el extra de v
Si extra(v)>2*cantidad de vértices entonces Terminar(ciclo de costo negativo)
Para cada vecino w de v
Si distancia(w)>distancia(v) + costovw
Actualizar distancia
Actualizar anterior
Poner a w en la cola si no está en ella, si ya está en la cola aumentar
extra en 2

6
6. Terminar satisfactoriamente

También podría gustarte