Está en la página 1de 15

Algoritmo de Bellman-Ford

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

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.
1 mtodo BellmanFord(Grafo,origen):
2
inicializamos las distancias con un valor grande
3
distancia[ origen ] = 0
4
para i = 1 hasta |V| - 1:
5
para cada arista E del Grafo:
6
sea ( u , v ) vrtices que unen la arista E
7
sea w el peso entre vrtices ( u , v )
8
Relajacion( u , v , w )
9
para cada arista E del Grafo:
10
sea ( u , v ) vrtices que unen la arista E
11
sea w el peso entre vrtices ( u , v )
12
si Relajacion( u , v , w )
13
Imprimir Existe ciclo negativo
15
Terminar Algoritmo
1 Relajacion( actual , adyacente , peso ):
2
si distancia[ actual ] + peso < distancia[ adyacente ]
3
distancia[ 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.

Cdigo
#define MAX 105 //maximo numero de vrtices
#define Node pair< int , int > //definimos el nodo como un par( first ,
second ) donde first es el vertice adyacente y second el peso de la
arista
#define INF 1<<30 //definimos un valor grande que represente la distancia
infinita inicial, basta conque sea superior al maximo valor del peso en
alguna de las aristas

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 co
int previo[ MAX ];
//para la impresion de caminos
int V;
//numero de vertices

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 infini
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

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


distancia[ inicial ] = 0;
//Este paso es importante,
inicializamos la distancia del inicial como 0
Hasta este momento la tabla quedara de la siguiente manera:

vrtices.

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 ver
int adyacente = ady[ actual ][ j ].v;
//id del vertice adyacente
int peso = ady[ actual ][ j ].w;
//peso de la arista que une actual con

}
}

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) adyacenteson los

vrtices que unen la arista e (en este caso seran los vrtices 2 y 4) y pesoson 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 ver
int adyacente = ady[ actual ][ j ].v;
//id del vertice adyacente
int peso = ady[ actual ][ j ].w;
//peso de la arista que une actual con
//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
if( distancia[ actual ] + peso < distancia[ adyacente ] ){
distancia[ adyacente ] = distancia[ actual ] + peso; //relajamos el vertice
previo[ adyacente ] = actual;
//a su vez actualizamo
Q.push( Node( adyacente , distancia[ adyacente ] ) ); //agregamos adyacente
}
}

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

->

5<7

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

2+8<8

->

10 < 8

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

2 + 5 < 13

->

7 < 13

Actualizamos distancias para los vrtices 2 y 5:

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:


//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 vertice actual
int adyacente = ady[ actual ][ j ].v;
//id del vertice
adyacente
int peso = ady[ actual ][ j ].w;
//peso de la arista
que une actual con adyacente ( origen , destino )
//Si aun es posible relajar la arista actual entonces tenemos
ciclo negativo
if( relajacion( actual , adyacente , peso ) ){
puts("Existe Ciclo Negativo");
return;
}
}
}

También podría gustarte