Sunteți pe pagina 1din 15

ALGORITMO DE BELLMAN-KALABA (FORD)

Descripcin
El algoritmo de Bellman-Ford determina la ruta ms corta desde un nodo origen hacia
los dems nodos para ello es requerido como entrada un grafo cuyas aristas posean
pesos. La diferencia de este algoritmo con los dems es que los pesos pueden tener
valores negativos ya que Bellman-Ford me permite detectar la existencia de un ciclo
negativo.
Como trabaja
El algoritmo parte de un vrtice origen que ser ingresado, Bellman-Ford simplemente
relaja todas las aristas y lo hace |V| 1 veces, siendo |V| el nmero de vrtices del
grafo.
Para la deteccin de ciclos negativos realizamos el paso de relajacin una vez ms y si
se obtuvieron mejores resultados es porque existe un ciclo negativo, para verificar
porque tenemos un ciclo podemos seguir relajando las veces que queramos y
seguiremos obteniendo mejores resultados.
Algoritmo en pseudocdigo
Considerar distancia[ i ] como la distancia ms corta del vrtice origen ingresado al
vrtice i y |V| el nmero de vrtices del grafo.
1mtodoBellmanFord(Grafo,origen):
2inicializamoslasdistanciasconunvalorgrande
3distancia[origen]=0
4para i = 1 hasta |V| - 1:
5para cada aristaEdelGrafo:
6sea(u,v)vrticesqueunenlaaristaE
7seawelpesoentrevrtices(u,v)
8Relajacion(u,v,w)
9para cada aristaEdelGrafo:
10sea(u,v)vrticesqueunenlaaristaE
11seawelpesoentrevrtices(u,v)
12siRelajacion(u,v,w)
13ImprimirExisteciclonegativo
15TerminarAlgoritmo

1 Relajacion(actual,adyacente,peso):
2sidistancia[actual]+peso<distancia[adyacente]
3distancia[adyacente]=distancia[actual]+peso

Ejemplo y Cdigo paso a paso


Tengamos el siguiente grafo, cuyos ID estn en color negro encima de cada vrtice, los
pesos esta en color azul y la distancia inicial en cada vrtice es infinito

Algunas consideraciones para entender el cdigo que se explicara junto con el


funcionamiento del algoritmo. Inicializamos los valores de nuestros arreglos:

Dnde:

Vrtices: ID de los vrtices.

Distancia[ u ]: Distancia ms corta desde vrtice inicial a vrtice con ID = u.

Previo[ u ]: Almacenara el ID del vrtice anterior al vrtice con ID = u, me


servir para impresin del camino ms corto.

En cuanto al cdigo los declaramos de la siguiente manera:

1
2
3
4

vector< Node > ady[ MAX ]; //lista de adyacencia


int distancia[ MAX ];
//distancia[ u ] distancia de vrtice inicial a vrtice con
int previo[ MAX ];
//para la impresion de caminos
int V;
//numero de vrtices

Y la funcin de inicializacin ser simplemente lo siguiente:

1
2
3
4
5
6
7

//funcin de inicializacin
void init(){
for( int i = 0 ; i <= V ; ++i ){
distancia[ i ] = INF; //inicializamos todas las distancias con valor infinito
previo[ i ] = -1;
//inicializamos el previo del vrtice i con -1
}
}

De acuerdo al vrtice inicial que elijamos cambiara la distancia inicial, por ejemplo la
ruta

ms

corta

partiendo

del

vrtice

todos

los

dems

vrtices.

Inicialmente la distancia de vrtice 1 -> vrtice 1 es 0 por estar en el mismo lugar.

distancia[ inicial ] = 0;
0

//Este paso es importante, inicializamos la distancia d

Hasta este momento la tabla quedara de la siguiente manera:

Ahora segn Bellman-Ford debemos realizar el paso de relajacin |V| 1 = 5 1 = 4


veces para cada arista:

1
2
3

for( int i = 1 ; i <= V - 1 ; ++i ){ //Iteramos |V| - 1 veces

Primera Iteracin
Empezamos con las aristas que parten del vrtice 1:

Como podemos observar tenemos 2 aristas, la que une vrtice 1 con vrtice 2 y vrtice
1 con vrtice 4. Ello en cdigo:

1
2
3
4
5
6
7

for( int actual = 1 ; actual <= V ; ++actual ){ //Estos dos for = O(E)
for( int j = 0 ; j < ady[ actual ].size() ; ++j ){ //reviso sus adyacentes del verti
int adyacente = ady[ actual ][ j ].v;
//id del vertice adyacente
int peso = ady[ actual ][ j ].w;
//peso de la arista que une actual con a
adyacente )

}
}

Las aristas de acuerdo al cdigo serian de la forma e = (actual , adyacente ,


peso)donde actual es el vrtice de donde partimos (en este caso sera 1) adyacente son
los vrtices que unen la arista e (en este caso seran los vrtices 2 y 4) y peso son los
pesos de cada arista (en este caso tendramos 7 y 2).
Evaluamos primero para vrtice 2:

Vemos que la distancia actual desde el vrtice inicial a 2 es , verifiquemos el paso de


relajacin:
distancia[ 1 ] + 7 < distancia[ 2 ]

->

0+7<

->

7<

El paso de relajacin es posible realizarlo entonces actualizamos la distancia en el


vrtice 2 quedando:

El paso de relajacin se dara en la siguiente parte:

1
2
3
4
5
6
7
8

for( int actual = 1 ; actual <= V ; ++actual ){ //Estos dos for = O(E)
for( int j = 0 ; j < ady[ actual ].size() ; ++j ){ //reviso sus adyacentes del verti
int adyacente = ady[ actual ][ j ].v;
//id del vertice adyacente
int peso = ady[ actual ][ j ].w;
//peso de la arista que une actual con a
adyacente )
//Realizamos paso de relajacion para la arista actual
relajacion( actual , adyacente , peso );
}
}

Donde la funcin de relajacin seria

1
2
3
4
5
6
7
8
9

//Paso de relajacion
void relajacion( int actual , int adyacente , int peso ){
//Si la distancia del origen al vertice actual + peso de su arista es menor a la di
adyacente
if( distancia[ actual ] + peso < distancia[ adyacente ] ){
distancia[ adyacente ] = distancia[ actual ] + peso; //relajamos el vertice ac
previo[ adyacente ] = actual;
//a su vez actualizamos e
Q.push( Node( adyacente , distancia[ adyacente ] ) ); //agregamos adyacente a l
}
}

Ahora evaluamos al siguiente adyacente que es el vrtice 4:

De manera similar al anterior vemos que la distancia actual desde el vrtice inicial a 4
es , verifiquemos el paso de relajacin:
distancia[ 1 ] + 2 < distancia[ 4 ]

->

0+2<

->

2<

El paso de relajacin es posible realizarlo entonces actualizamos la distancia en el


vrtice 4 quedando:

Hemos terminado las aristas que parten del vrtice 1, continuamos con las aristas que
parten del vrtice 2:

Comenzamos por el vrtice 3 y realizamos paso de relajacin:


distancia[ 2 ] + 1 < distancia[ 3 ]

->

7+1<

->

8<

En esta oportunidad hemos encontrado una ruta ms corta partiendo desde el vrtice
inicial al vrtice 3, actualizamos la distancia en el vrtice 3 y actualizamos el vrtice
previo al actual quedando:

Ahora continuamos con la arista que une al vrtice 2 con el vrtice 4:

En este caso vemos que no se lleva acabo el paso de relajacin:


distancia[ 2 ] + 2 < distancia[ 4 ]

->

7+2<2

->

9<2

Por lo tanto no actualizamos valores en la tabla. Ahora el siguiente vrtice a evaluar es


el vrtice 3 que posee una sola arista:

Como el peso de su vrtice adyacente es infinito actualizamos la distancia:

Ahora el siguiente vrtice a evaluar es el vrtice 4 que posee cuatro aristas:

Realizamos paso de relajacin para cada vrtice adyacente:


Con vrtice 2: distancia[ 4 ] + 3 < distancia[ 2 ]

->

2+3<7

Con vrtice 3: distancia[ 4 ] + 8 < distancia[ 3 ]

->

2+8<8

Con vrtice 5: distancia[ 4 ] + 5 < distancia[ 5 ]

->

Actualizamos distancias para los vrtices 2 y 5:

2 + 5 < 13

->
->
->

5<7
10 < 8
7 < 13

Ahora continuamos con vrtice 5:

En este caso no actualizamos las distancias. Hemos terminado la primera iteracin,


continuemos:
Segunda Iteracin:
Luego de la segunda iteracin obtendremos lo siguiente:

En esta iteracin solamente se realiz el paso de relajacin en la arista que une vrtices
2 y 3. Para el grafo dado en la segunda iteracin ya habremos obtenido la ruta ms
corta partiendo del vrtice 1 a todos los dems vrtices. Sin embargo no siempre
obtendremos el ptimo en la 2da iteracin, todo depender del grafo ingresado.
Impresin del Camino Ms Corto
La impresin del camino ms corto dado un vrtice destino es de la misma forma como
se explic en el tutorial del Algoritmo de Dijkstra.
Deteccin de Ciclo Negativo
Para la deteccin de ciclo negativo tomaremos como ejemplo el grafo siguiente:

Asumimos que el vrtice inicial es el vrtice 1, tendremos que realizar 2 iteraciones.


Primera Iteracin

Empezamos por el vrtice 1:

Continuamos con el vrtice 2:

Continuamos con el vrtice 3:

Segunda Iteracin
En esta ltima iteracin se relajan vrtices 2 y 3:

Hemos terminado el nmero de iteraciones que tenamos que realizar. Para verificar la
existencia de un ciclo negativo, segn el algoritmo de Bellman-Ford, realizamos el paso
de relajacin sobre todas las aristas una vez ms:

Como se pudo realizar el paso de relajacin entonces existe un ciclo negativo:

1
2
3
4
5
6
7
8
9
10
11
12

//Comprobamos si hay ciclo negativo en el grafo ingresado


for( int actual = 1 ; actual <= V ; ++actual ){ //Estos dos for = O(E)
for( int j = 0 ; j < ady[ actual ].size() ; ++j ){ //reviso sus adyacentes del
int adyacente = ady[ actual ][ j ].v;
//id del vertice adyacente
int peso = ady[ actual ][ j ].w;
//peso de la arista que une actual
destino )
//Si aun es posible relajar la arista actual entonces tenemos ciclo negat
if( relajacion( actual , adyacente , peso ) ){
puts("Existe Ciclo Negativo");
return;
}
}
}

Problemas de diferentes Jueces

S-ar putea să vă placă și