Você está na página 1de 36

Investigacin de las operaciones II

Cadenas de Markov
Algoritmo de Dijkstra y Floyd

Prof. Alma Delia Corrales Orozco

Rogelio Ledesma Martnez

Nm. De control12210535

Tijuana B.C. 22 de mayo del 2015

Algoritmo DIJKSTRA.
Para el problema de la ruta corta tenemos varios algoritmos, en esta
oportunidad se explicar el algoritmo de dijkstra el cual usa una tcnica
voraz (greedy). Al final del articulo se encuentran adjuntas las
implementaciones en C++ y JAVA.
Descripcin
El algoritmo de dijkstra 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. Algunas consideraciones:

Si los pesos de mis aristas son de valor 1, entonces bastar


con usar el algoritmo de BFS.
Si los pesos de mis aristas son negativos no puedo usar el
algoritmo de dijsktra, para pesos negativos tenemos otro
algoritmo llamado Algoritmo de Bellmand-Ford.

Como trabaja
Primero marcamos todos los vrtices como no utilizados. El algoritmo
parte de un vrtice origen que ser ingresado, a partir de ese vrtices
evaluaremos sus adyacentes, como dijkstra usa una tcnica greedy La
tcnica greedy utiliza el principio de que para que un camino sea ptim

o, todos los caminos que


contiene tambin deben ser ptimos- entre todos los vrtices
adyacentes, buscamos el que est ms cerca de nuestro punto origen, lo
tomamos como punto intermedio y vemos si podemos llegar ms rpido
a travs de este vrtice a los dems. Despus escogemos al siguiente
ms cercano (con las distancias ya actualizadas) y repetimos el proceso.
Esto lo hacemos hasta que el vrtice no utilizado ms cercano sea

nuestro destino. Al proceso de actualizar las distancias tomando como


punto intermedio al nuevo vrtice se le conoce como relajacin
(relaxation).
Dijkstra es muy similar a BFS, si recordamos BFS usaba una Cola para el
recorrido para el caso de Dijkstra usaremos una Cola de Prioridad o
Heap, este Heap debe tener la propiedad de Min-Heap es decir cada vez
que extraiga un elemento del Heap me debe devolver el de menor valor,
en nuestro caso dicho valor ser el peso acumulado en los nodos.
Tanto java como C++ cuentan con una cola de prioridad ambos
implementan un Binary Heap aunque con un Fibonacci Heap la
complejidad de dijkstra se reduce hacindolo mas eficiente, pero en un
concurso mas vale usar la librera que intentar programar una nueva
estructura como un Fibonacci Heap, claro que particularmente uno
puede investigar y programarlo para saber como funciona internamente.
Algoritmo en pseudocdigo
Considerar distancia[ i ] como la distancia mas corta del vrtice origen
ingresado al vrtice i.
1 mtodo Dijkstra(Grafo,origen): 2
creamos una cola de prioridad Q
3
agregamos origen a la cola de prioridad Q 4
mientras Q no este
vaco: 5
sacamos un elemento de la cola Q llamado u 6
si u
ya fue visitado continuo sacando elementos de Q
7
marcamos
como visitado u 8
para cada vrtice v adyacente a u en el Grafo:
9
sea w el peso entre vrtices ( u , v ) 10
si v no ah sido
visitado: 11
Relajacion( u , v , w ) 1 mtodo Relajacion( actual
, adyacente , peso ): 2
si distancia[ actual ] + peso <
distancia[ adyacente ] 3
distancia[ adyacente ] = distancia[ actual ]
+ peso 4
agregamos adyacente a la cola de prioridad Q
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.
#define MAX 10005 //maximo numero de vrtices
#define Node pair< int , int > //definimos el nodo como un par( first ,
1second ) donde first es el vertice adyacente y second el peso de la
2arista
3#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

Donde:
Vrtices: ID de los vrtices.
Distancia[ u ]: Distancia mas corta desde vrtice inicial a vrtice
con ID = u.
Visitado[ u ]: 0 si el vrtice con ID = u no fue visitado y 1 si ya
fue visitado.
Previo[ u ]: Almacenara el ID del vrtice anterior al vrtice con ID
= u, me servir para impresin del camino mas corto.

En cuanto al cdigo los declaramos de la siguiente manera:


vector< Node > ady[ MAX ]; //lista de adyacencia
int distancia[ MAX ];
//distancia[ u ] distancia de vrtice inicial a
1
vrtice con ID = u
2
bool visitado[ MAX ];
//para vrtices visitados
3
int previo[ MAX ];
//para la impresion de caminos
4
priority_queue< Node , vector<Node> , cmp > Q; //priority queue
5
propia del c++, usamos el comparador definido para que el de menor
6
valor este en el tope
int V;
//numero de vertices
Y la funcin de inicializacin ser simplemente lo siguiente
//funcin de inicializacin
1void init(){
2 for( int i = 0 ; i <= V ; ++i ){
3
distancia[ i ] = INF; //inicializamos todas las distancias con valor
4infinito
5
visitado[ i ] = false; //inicializamos todos los vrtices como no
6visitado
7
previo[ i ] = -1;
//inicializamos el previo del vrtice i con -1
8 }
}
De acuerdo al vrtice inicial que elijamos cambiara la distancia inicial,
por ejemplo la ruta ms corta partiendo del vrtice 1 a todos los dems
vrtices:

El vrtice 1 es visitado, la distancia de vrtice 1 -> vrtice 1 es 0 por


estar en el mismo lugar.
Q.push( Node( inicial , 0 ) ); //Insertamos el vrtice inicial en la Cola de
1Prioridad
2distancia[ inicial ] = 0;
//Este paso es importante, inicializamos la
distancia del inicial como 0

Extraemos el tope de la cola de prioridad


while( !Q.empty() ){
//Mientras cola no este vacia
1
actual = Q.top().first;
//Obtengo de la cola el nodo con
2
menor peso, en un comienzo ser el inicial
3
Q.pop();
//Sacamos el elemento de la cola
Si el tope ya fue visitado entonces no tengo necesidad de evaluarlo, por
ello continuara extrayendo elementos dela cola:
if( visitado[ actual ] ) continue; //Si el vrtice actual ya fue visitado
1
entonces sigo sacando elementos de la cola
En este caso al ser el tope el inicial no esta visitado por lo tanto
marcamos como visitado.
1visitado[ actual ] = true;
//Marco como visitado el vrtice actual
Hasta este momento la tabla quedara de la siguiente manera

Ahora vemos sus adyacentes que no hayan sido visitados. Tendramos 2


y 4.
for( int i = 0 ; i < ady[ actual ].size() ; ++i ){ //reviso sus adyacentes
del vertice actual
1
adyacente = ady[ actual ][ i ].first; //id del vertice adyacente
2
peso = ady[ actual ][ i ].second;
//peso de la arista que une
3
actual con adyacente ( actual , adyacente )
4
if( !visitado[ adyacente ] ){
//si el vertice adyacente no fue
visitado
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 y agregando el vrtice en la cola de prioridad
con nueva distancia quedando:

El paso de relajacin se dara en la siguiente parte:


for( int i = 0 ; i < ady[ actual ].size() ; ++i ){ //reviso sus adyacentes
del vertice actual
1 adyacente = ady[ actual ][ i ].first; //id del vertice adyacente
2 peso = ady[ actual ][ i ].second;
//peso de la arista que une
3actual con adyacente ( actual , adyacente )
4 if( !visitado[ adyacente ] ){
//si el vertice adyacente no fue
5visitado
6
relajacion( actual , adyacente , peso ); //realizamos el paso de
7relajacion
}
}
Donde la funcin de relajacin seria
//Paso de relajacion
void relajacion( int actual , int adyacente , int peso ){
1 //Si la distancia del origen al vertice actual + peso de su arista es
2menor a la distancia del origen al vertice adyacente
3 if( distancia[ actual ] + peso < distancia[ adyacente ] ){
4
distancia[ adyacente ] = distancia[ actual ] + peso; //relajamos el
5vertice actualizando la distancia
6
previo[ adyacente ] = actual;
//a su vez
7actualizamos el vertice previo
8
Q.push( Node( adyacente , distancia[ adyacente ] ) ); //agregamos
9adyacente a la cola de prioridad
}
}
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:

En cuanto a la cola de prioridad como tenemos un vrtice con menor


peso este nuevo vrtice ira en el tope de la cola:

Revisamos sus adyacentes no visitados que serian vrtices 2, 3 y 5.


Empecemos por el vrtice 2:

Ahora vemos que la distancia actual del vrtice inicial al vrtice 2 es 7,


verifiquemos el paso de relajacin:
distancia[ 4 ] + 3 < distancia[ 2 ]
->
2+3<7
->
5<7

En esta oportunidad hemos encontrado una ruta mas corta partiendo


desde el vrtice inicial al vrtice 2, actualizamos la distancia en el
vrtice 2 y actualizamos el vrtice previo al actual quedando:

En cuanto a la cola de prioridad como tenemos un vrtice con menor


peso este nuevo vrtice ira en el tope de la cola, podemos ver que
tenemos 2 veces el mismo vrtice pero como usamos una tcnica
greedy siempre usaremos el valor ptimo:

Continuamos con los Vrtices 3 y 5 como tienen valor si ser posible


relajarlos por lo que sera similar a los pasos iniciales solo que en los
pasos iniciales distancia[ 1 ] era 0 en este caso distancia[ 4 ] es 2,
quedando:

Hemos terminado de evaluar al vrtice 4, continuamos con el tope de la


cola que es vrtice 2, el cual marcamos como visitado.

Los adyacentes no visitados del vrtice 2 son los vrtices 3 y 5.


Comencemos con el vrtice 3

Ahora vemos que la distancia actual del vrtice inicial al vrtice 3 es 10,
verifiquemos el paso de relajacin:
distancia[ 2 ] + 1 < distancia[ 3 ]
->
5 + 1 < 10
->
6 < 10
En esta oportunidad hemos encontrado una ruta mas corta partiendo
desde el vrtice inicial al vrtice 3, dicha ruta sera 1 -> 4 -> 2 -> 3 cuyo
peso es 6 que es mucho menor que la ruta 1 > 4 -> 3 cuyo peso es 10,
actualizamos la distancia en el vrtice 3 quedando:

El siguiente vrtice de la cola de prioridad es el vrtice 3 y su nico


adyacente no visitado es el vrtice 5.

Vemos que la distancia actual del vrtice inicial al vrtice 5 es 7,


verifiquemos el paso de relajacin:
distancia[ 3 ] + 5 < distancia[ 5 ]
->
6+5<7
->
11 < 7
En esta oportunidad se no cumple por lo que no relajamos el vrtice 5,
por lo que la tabla en cuanto a distancias no sufre modificaciones y no
agregamos vrtices a la cola:

Ahora tocara el vrtice 2 pero como ya fue visitado seguimos


extrayendo elementos de la cola, el siguiente vrtice ser el 5.

Al ser el ultimo vrtice a evaluar no posee adyacentes sin visitar por lo


tanto hemos terminado el algoritmo. En el grafico anterior observamos
que 2 aristas no fueron usadas para la relajacin, las dems si fueron
usadas. La tabla final quedara de la siguiente manera:

De la tabla si deseo saber la distancia mas corta del vrtice 1 al vrtice


5, solo tengo que acceder al valor del arreglo en su ndice respectivo
(distancia[ 5 ]).
Shortest Path Tree
En el proceso anterior usbamos el arreglo previo[ u ] para almacenar el
ID del vrtice previo al vrtice con ID = u, ello me sirve para formar el
rbol de la ruta mas corta y adems me sirve para imprimir caminos de
la ruta mas corta.

Impresin del camino encontrado.


Para imprimir el camino mas corto deseado usamos el arreglo
previo[ u ], donde u tendr el ID del vrtice destino, o sea si quiero
imprimir el camino mas corto desde vrtice 1 -> vrtice 3 partir desde
previo[ 3 ] hasta el previo[ 1 ]. De manera similar a lo que se explico en
el algoritmo BFS, en este caso se realizara de manera recursiva:
//Impresion del camino mas corto desde el vertice inicial y final
1ingresados
2void print( int destino ){
3 if( previo[ destino ] != -1 ) //si aun poseo un vertice previo
4
print( previo[ destino ] ); //recursivamente sigo explorando
5 printf("%d " , destino );
//terminada la recursion imprimo los
6vertices recorridos
}
Veamos grficamente el funcionamiento, desde el grafo comenzamos en
3

El previo de 3 es el vrtice 2, por lo tanto ahora evalu 2:

Ahora el previo de 2 es el vrtice 4:

El previo de 4 es el vrtice inicial 1

Como el previo de 1 es -1 terminamos el recorrido, ahora en el retorno


de las llamadas recursivas imprimo el camino: 1 4 2 3

Algoritmo de FLOYD
El algoritmo de Floyd es ms general que el de Dijkstra, ya que
determina la ruta ms corta entre dos nodos cualquiera de la red.
El algoritmo representa una red de n nodos como una matriz
cuadrada de orden n, la llamaremos matriz C. De esta forma, el
valor Cij representa el coste de ir desde el nodo i al nodo j,
inicialmente en caso de no existir un arco entre ambos, el valor Cij
ser infinito.
Definiremos otra matriz D, tambin cuadrada de orden n, cuyos
elementos van a ser los nodos predecesores en el camino hacia el
nodo origen, es decir, el valor Dij representar el nodo predecesor
a j en el camino mnimo desde i hasta j. Inicialmente se comienza
con caminos de longitud 1, por lo que Dij = i.
Las diagonales de ambas matrices representan el coste y el nodo
predecesor para ir de un nodo a si mismo, por lo que no sirven
para nada, estarn bloqueadas.
Los pasos a dar en la aplicacin del algoritmo de Floyd son los
siguientes:
Formar las matrices iniciales C y D.
Se toma k=1.
Se selecciona la fila y la columna k de la matriz C y entonces, para
i y j, con ik, jk e ij, hacemos:
Si (Cik + Ckj) < Cij Dij = Dkj y Cij = Cik + Ckj
En caso contrario, dejamos las matrices como estn.
Si k n, aumentamos k en una unidad y repetimos el paso
anterior, en caso contrario paramos las iteraciones.
La matriz final C contiene los costes ptimos para ir de un vrtice
a otro, mientras que la matriz D contiene los penltimos vrtices
de los caminos ptimos que unen dos vrtices, lo cual permite
reconstruir cualquier camino ptimo para ir de un vrtice a otro.
Ejemplo: Aplicar el algoritmo de Floyd sobre el siguiente grafo para
obtener las rutas ms cortas entre cada dos nodos. El arco (3, 5) es
direccional, de manera que no est permitido ningn trfico del nodo 5
al nodo 3 . Todos los dems arcos permiten el trfico en ambas
direcciones.

Inicializamos las matrices :

Tomamos k=1:

Tomamos i=2 (i k):


j=3 (jk, ji): C[2,1]+C[1,3] = 3+10 = 13 < C[2,3] = , por tanto
hacemos:
C[2,3] = 13 y D[2,3] = 1.
j=4 (jk, ji): C[2,1]+C[1,4] = 3+ = , no hay que cambiar
nada, no podemos llegar de 2 a 4 a travs de 1.
j=5 (jk, ji): C[2,1]+C[1,5] = 3+ = , no hay que cambiar
nada, no podemos llegar de 2 a 5 a travs de 1.
Tomamos i=3 (i k):
o j=2 (jk, ji): C[3,1]+C[1,2] = 10+3 = 13 < C[3,2] = , por
tanto hacemos:
C[3,2] = 13 y D[3,2] = 1.
j=4 (jk, ji): C[3,1]+C[1,4] = 10+ = , no hay que cambiar
nada, no podemos llegar de 3 a 4 a travs de 1.
j=5 (jk, ji): C[3,1]+C[1,5] = 10+ = , no hay que cambiar
nada, no podemos llegar de 3 a 5 a travs de 1.
Tomamos i=4 (i k):
o j=2 (jk, ji): C[4,1]+C[1,2] = +3 = , no hay que
cambiar nada, no podemos llegar de 4 a 2 a travs de 1.
o j=3 (jk, ji): C[4,1]+C[1,3] = +10 = , no hay que
cambiar nada, no podemos llegar de 4 a 3 a travs de 1.
o j=5 (jk, ji): C[4,1]+C[1,5] = + = , no hay que
cambiar nada, no podemos llegar de 4 a 5 a travs de 1.
Tomamos i=5 (i k), en este caso ocurre como en el paso anterior, como
C[5,1]=, entonces no habr ningn cambio, no puede haber ningn
camino desde 5 a travs de 1.

Tomamos k=2:

Tomamos i=1:
j=3: C[1,2]+C[2,3] = 3+13 = 16 > C[1,3] = 10 , por tanto no hay
que cambiar nada, el camino es mayor que el existente.
j=4: C[1,2]+C[2,4] = 3+5 = 8 < C[1,4] = , por tanto hacemos:
C[1,4] = 8 y D[1,4] = 2 .
j=5: C[1,2]+C[2,5] = 3+ = , no hay que cambiar nada.
Tomamos i=3:
o j=1: C[3,2]+C[2,1] = 13+3 = 16 > C[3,1] = 10, no hay que
cambiar nada.
o j=4: C[3,2]+C[2,4] = 13+5 = 18 > C[3,4] = 6, no hay que
cambiar nada.
o j=5: C[3,2]+C[2,5] = 13+ = , no hay que cambiar nada.
Tomamos i=4:
o j=1: C[4,2]+C[2,1] = 5+3 = 8 < C[4,1] = , por tanto
hacemos:
C[4,1] = 8 y D[4,1] = 2.
j=3: C[4,2]+C[2,3] = 5+13 = 18 > C[4,3] = 6, no hay que cambiar
nada.
j=5: C[4,2]+C[2,5] = 5+ = , no hay que cambiar nada.
Tomamos i=5, como C[5,2]=, entonces no habr ningn cambio.

Tomamos k=3:

Tomamos i=1:
o j=2: C[1,3]+C[3,2] = 10+13 = 23 > C[1,2] = 3, no hay que
cambiar nada.
o j=4: C[1,3]+C[3,4] = 10+6 = 16 > C[1,4] = 8, no hay que
cambiar nada.
o j=5: C[1,3]+C[3,5] = 10+15 = 25 < C[1,5] = , por tanto
hacemos:
C[1,5] = 25 y D[1,5] = 3 .
Tomamos i=2:
o j=1: C[2,3]+C[3,1] = 13+10 = 23 > C[2,1] = 3, no hay que
cambiar nada.
o j=4: C[2,3]+C[3,4] = 13+6 = 19 > C[2,4] = 5, no hay que
cambiar nada.
o j=5: C[2,3]+C[3,5] = 13+15 = 28 < C[2,5] = , por tanto
hacemos:
C[2,5] = 28 y D[2,5] = 3.
Tomamos i=4:
o j=1: C[4,3]+C[3,1] = 6+10 = 16 > C[4,1] = 8, no hay que
cambiar nada.
o j=2: C[4,3]+C[3,2] = 6+13 = 19 > C[4,2] = 5, no hay que
cambiar nada.
o j=5: C[4,3]+C[3,5] = 6+15 = 21 > C[4,5] = 4, no hay que
cambiar nada.
Tomamos i=5, como C[5,3]=, entonces no habr ningn cambio.

Tomamos k=4:

Tomamos i=1:
o j=2: C[1,4]+C[4,2] = 8+5 = 13 > C[1,2] = 3, no hay que
cambiar nada.
o j=3: C[1,4]+C[4,3] = 8+6 = 14 > C[1,3] = 10, no hay que
cambiar nada.
o j=5: C[1,4]+C[4,5] = 8+4 = 12 < C[1,5] = 25, por tanto
hacemos:
C[1,5] = 12 y D[1,5] = 4.
Tomamos i=2:
o j=1: C[2,4]+C[4,1] = 5+8 = 13 > C[2,1] = 3, no hay que
cambiar nada.
o j=3: C[2,4]+C[4,3] = 5+6 = 11 < C[2,3] = 13, por tanto
hacemos:
C[2,3] = 11 y D[2,3] = 4.
j=5: C[2,4]+C[4,5] = 5+4 = 9 < C[2,5] = 28, por tanto hacemos:
C[2,5] = 9 y D[2,5] = 4.
Tomamos i=3:
o j=1: C[3,4]+C[4,1] = 6+8 = 14 > C[3,1] = 10, no hay que
cambiar nada.
o j=2: C[3,4]+C[4,2] = 6+5 = 11 < C[3,2] = 13, por tanto
hacemos:
C[3,2] = 11 y D[3,2] = 4.
j=5: C[3,4]+C[4,5] = 6+4 = 10 < C[3,5] = 15, por tanto hacemos:
C[3,5] = 10 y D[3,5] = 4.
Tomamos i=5:
o j=1: C[5,4]+C[4,1] = 4+8 = 12 < C[5,1] = , por tanto
hacemos:
C[5,1] = 12 y D[5,1] = 2 .
j=2: C[5,4]+C[4,2] = 4+5 = 9 < C[5,2] = , por tanto hacemos:
C[5,2] = 9 y D[5,2] = 4.

j=3: C[5,4]+C[4,3] = 4+6 = 10 < C[5,3] = , por tanto hacemos:


C[5,3] = 10 y D[5,3] = 4.
Tomamos k=5:

Tomamos i=1:
o j=2: C[1,5]+C[5,2]
cambiar nada.
o j=3: C[1,5]+C[5,3]
cambiar nada.
o j=4: C[1,5]+C[5,4]
cambiar nada.
Tomamos i=2:
o j=1: C[2,5]+C[5,1]
cambiar nada.
o j=3: C[2,5]+C[5,3]
cambiar nada.
o j=4: C[2,5]+C[5,4]
cambiar nada.
Tomamos i=3:
o j=1: C[3,5]+C[5,1]
cambiar nada.
o j=2: C[3,5]+C[5,2]
cambiar nada.
o j=4: C[3,5]+C[5,4]
cambiar nada.
Tomamos i=4:
o j=1: C[4,5]+C[5,1]
cambiar nada.
o j=2: C[4,5]+C[5,2]
cambiar nada.
o j=3: C[4,5]+C[5,3]

= 12+9 = 21 > C[1,2] = 3, no hay que


= 12+10 = 22 > C[1,3] = 10, no hay que
= 12+4 = 16 > C[1,4] = 8, no hay que
= 9+12 = 21 > C[2,1] = 3, no hay que
= 9+10 = 19 > C[2,3] = 11, no hay que
= 9+4 = 13 > C[2,4] = 5, no hay que
= 10+12 = 22 > C[3,1] = 10, no hay que
= 10+9 = 19 > C[3,2] = 11, no hay que
= 10+4 = 14 > C[3,4] = 6, no hay que
= 4+12 = 16 > C[4,1] = 8 , no hay que
= 4+9 = 13 > C[4,2] = 5 , no hay que
= 4+10 = 14 > C[4,3] = 6, no hay que

cambiar nada.
FIN del proceso, las matrices quedan como sigue:

Las matrices finales C y D contienen toda la informacin necesaria


para determinar la ruta ms corta entre dos nodos cualquiera de la
red. Por ejemplo, la distancia ms corta del nodo 1 al nodo 5 es
C[1,5] = 12.
Para determinar la ruta asociada del camino mnimo entre el nodo
1 y el nodo 5 haremos lo siguiente:
o Consultamos D[1,5]=4, por tanto el nodo predecesor al 5 es
el 4, es decir, 4 5.
o Consultamos D[1,4]=2, por tanto el nodo predecesor al 4 es
el 2, es decir, 2 4 5.
Consultamos D[1,2]=1, por tanto el nodo predecesor al 2 es el 1, es
decir, 1 2 4 5, y as ya tenemos la ruta completa.

Algoritmo de Floyd:
En informtica, el algoritmo de Floyd-Warshall, descrito en 1959 por
Bernard Roy, es un algoritmo de anlisis sobre grafos para encontrar el
camino mnimo en grafos dirigidos ponderados. El algoritmo encuentra
el camino entre todos los pares de vrtices en una nica ejecucin. El
algoritmo de Floyd-Warshall es un ejemplo de programacin dinmica.
Aplicaciones:
El algoritmo de Floyd-Warshall puede ser utilizado para resolver los
siguientes problemas, entre otros:
Camino mnimo en grafos dirigidos (algoritmo de Floyd).
Cierre transitivo en grafos dirigidos (algoritmo de Warshall). Es la
formulacin original del algoritmo de Warshall. El grafo es un grafo
no ponderado y representado por una matriz booleana de
adyacencia. Entonces la operacin de adicin es reemplazada por

la conjuncin lgica(AND) y la operacin menor por la disyuncin


lgica (OR).
Encontrar una expresin regular dada por un lenguaje regular
aceptado por un autmata finito (algoritmo de Kleene).
Inversin de matrices de nmeros reales (algoritmo de GaussJordan).
Ruta optima. En esta aplicacin es interesante encontrar el camino
del flujo mximo entre 2 vrtices. Esto significa que en lugar de
tomar los mnimos con el pseudocodigo anterior, se coge el
mximo. Los pesos de las aristas representan las limitaciones del
flujo. Los pesos de los caminos representan cuellos de botella; por
ello, la operacin de adicin anterior es reemplazada por la
operacin mnimo.
Comprobar si un grafo no dirigido es bipartito.

Ejemplo:
Hallar el camino mnimo desde el vrtice 3 hasta 4 en el grafo con la
siguiente matriz de distancias:

Aplicamos el algoritmo de Floyd-Warshall, y para ello en cada iteracin


fijamos un vrtice intermedio.
1 Iteracin: nodo intermedio = 1
La matriz es simtrica, por lo que solamente har falta calcular el
tringulo superior de las distancias.
d23 = min(d23, d21 + d13) = 8
d24 = min(d24, d21 + d14) = 4
d25 = min(d25, d21 + d15) = 9
d26 = min(d26, d21 + d16) =
d32 = min(d32, d31 + d12) = 8
d34 = min(d34, d31 + d14) = 6
d35 = min(d35, d31 + d15) = 7
d36 = min(d36, d31 + d16) = 1
d45 = min(d45, d41 + d15) =
d46 = min(d46, d41 + d16) = 4

d56 = min(d56, d51 + d16) =


La matriz de distancia despus de esta iteracin es:

2 Iteracin: nodo intermedio = 2


d13 = min(d13, d12 + d23) = 5
d14 = min(d14, d12 + d24) = 1
d15 = min(d15, d12 + d25) = 12
d16 = min(d16, d12 + d26) =
d34 = min(d34, d32 + d24) = 6
d35 = min(d35, d32 + d25) = 7
d36 = min(d36, d32 + d26) = 1
d45 = min(d45, d42 + d25) = 13
d46 = min(d46, d42 + d26) = 4
d56 = min(d56, d52 + d26) =
La matriz de distancia despus de esta iteracin es:

3 Iteracin: nodo intermedio = 3


d12 = min(d12, d13 + d32) = 3
d14 = min(d14, d13 + d34) = 1
d15 = min(d15, d13 + d35) = 12
d16 = min(d16, d13 + d36) = 6
d24 = min(d24, d23 + d34) = 4
d25 = min(d25, d23 + d35) = 9
d26 = min(d26, d23 + d36) = 9
d45 = min(d45, d43 + d35) = 13
d46 = min(d46, d43 + d36) = 4

d56 = min(d56, d53 + d36) = 8


La matriz de distancia despus de esta iteracin es:

4 Iteracin: nodo intermedio = 4


d12 = min(d12, d14 + d42) = 3
d13 = min(d13, d14 + d43) = 5
d15 = min(d15, d14 + d45) = 12
d16 = min(d16, d14 + d46) = 5
d23 = min(d23, d24 + d43) = 8
d25 = min(d25, d24 + d45) = 9
d26 = min(d26, d24 + d46) = 8
d35 = min(d35, d34 + d45) = 7
d36 = min(d36, d34 + d46) = 1
d56 = min(d56, d54 + d46) = 8
La matriz de distancia despus de esta iteracin es:

5 Iteracin: nodo intermedio = 5


d12 = min(d12, d15 + d52) = 3
d13 = min(d13, d15 + d53) = 5
d14 = min(d14, d15 + d54) = 1
d16 = min(d16, d15 + d56) = 5
d23 = min(d23, d25 + d53) = 8
d24 = min(d24, d25 + d54) = 4
d26 = min(d26, d25 + d56) = 8
d34 = min(d34, d35 + d54) = 6
d36 = min(d36, d35 + d56) = 1

d46 = min(d46, d45 + d56) = 4


La matriz de distancia despus de esta iteracin es:

6 Iteracin: nodo intermedio = 6


d12 = min(d12, d16 + d62) = 3
d13 = min(d13, d16 + d63) = 5
d14 = min(d14, d16 + d64) = 1
d15 = min(d15, d16 + d65) = 12
d23 = min(d23, d26 + d63) = 8
d24 = min(d24, d26 + d64) = 4
d25 = min(d25, d26 + d65) = 9
d34 = min(d34, d36 + d64) = 5
d35 = min(d35, d36 + d65) = 7
d45 = min(d45, d46 + d65) = 12
La matriz de distancia despus de esta iteracin es:

Ya se han hecho todas las iteraciones posibles. Por tanto, el camino


mnimo entre 2 vrtices cualesquiera del grafo ser el obtenido en la
matriz final. En este caso, el camino mnimo entre 3 y 4 vale 5.

Cadenas de Markov.

Você também pode gostar