Está en la página 1de 89

Algoritmos sobre grafos

Luis Fernando Niño V., Ph.D.


lfninov@unal.edu.co

Departamento de Ingeniería de Sistemas e


Industrial

2017
Agenda

Abstracción

Implementación
Agenda

Abstracción

Implementación
Abstracción
Tipo de Dato Abstracto (TDA)

Datos?

Operaciones?

Independiente de la implementación computacional!!!


Abstracción
Algoritmos sobre grafos

1. Ordenación topológica (topsort)

2. Camino más corto


Abstracción Estructuras de datos no lineales
Estructuras lineales: cada elemento tiene máximo
un sucesor y un antecesor
Estructuras no lineales: cada elemento puede
tener varios sucesores y antecesores
Abstracción Estructuras de datos no lineales
Abstracción Estructuras de datos no lineales

árbol

grafo
Abstracción Recorridos sobre grafos

• Recorrido en anchura o amplitud (Breadth first


search, BFS)

• Recorrido en profundidad (Depth first search,


DFS)
Abstracción Recorrido en anchura (amplitud)
• Dado un vértice origen s, sistemáticamente se exploran
los arcos del grafo G y se van descubriendo todos los
vértices alcanzables desde s.
• Se visitan primero los nodos a la misma “distancia”, y
se incrementa gradualmente la distancia
• Se llega a los nodos de distancia k, sólo luego de haber
llegado a todos los nodos a distancia k-1.
• A medida que se avanza se puede pensar que se
generando un árbol con raíz en s y que contiene a
todos los vértices alcanzables desde s.
• El camino desde s a cada vértice en este recorrido
contiene el mínimo número de arcos
• Expande uniformemente la frontera entre lo descubierto
y lo no descubierto.
Abstracción Recorrido en anchura (amplitud)
Ejemplo
r s t u r s t u
 0   1 0  
(a) Q s (b) Q wr
    0  1   11
v w x y v w x y
r s t u r s t u
1 0 2  1 0 2 
Q r tx Q t xv
(c) 122 (d
 1 2  2 1 2  222
w x y ) v w x y
v u u
r s t r s t
1 0 2 3 1 0 2 3
Q xvu
(e) 2 223
(f) Q vuy
1 2  2 1 2 3 233
v w x y v w x y
r s t u r s t u
1 0 2 3 1 0 2 3
Q uy Q y
(g) (h)
2 1 2 3 33 2 1 2 3 3
v w x y v w x y
r s t u
1 0 2 3 
(i) Q
2 1 2 3
y 11
v w x
Abstracción Recorrido en anchura (amplitud)
// Inicialmente el algoritmo colorea los vértices con blanco. Luego éstos pasan a gris y luego negro. El color gris
// es usado para definir la frontera entre lo ya descubierto o explorado y lo por visitar.

•BFS(G,s) { /* pseudo-código */
int d[N], p[N], color[N]; /* Arreglos de distancia, de padres, y de color */
QUEUE Q; /* Cola usada como estructura auxiliar */
for ( cada vértice u  V[G] -{s}) {
color [u] =Blanco;
d[u] = ; /* distancia infinita si el nodo no es alcanzable */
}
color[s] =Gris;
d[s] = 0;
p [s]=NULL;
Enqueue(Q, s);
while ( !Queue_Vacía(Q) ) {
u = Cabeza(Q); /* u es el primer nodo de la cola */
for ( cada v  Adj [u] ) {
if (color [v] == Blanco) {
color[v]=Gris; /* Gris al entrar a la cola */
d [v]=d [u] +1;
p [v] = u;
Enqueue(Q, v);
}
Dequeue(Q); /* se extrae u */
color [u] = Negro; /* negro luego de salir de la cola */
}
}

Tiempo de ejecución: O(|V|+|E|).


* cada nodo es encolado una vez y su lista de adyacencia es
recorrida una vez.
Abstracción Recorrido en profundidad

Se buscan los caminos que parten desde el nodo origen s


hasta que ya no es posible avanzar más.

Cuando ya no puede avanzarse más sobre el camino elegido,
se vuelve atrás en busca de caminos alternativos.
Abstracción Recorrido en profundidad
// inicialmente el algoritmo colorea los vértices con blanco. Luego éstos pasan a gris y luego negro. En DFS el
// color gris es usado para definir nodos cuyos descendientes están siendo visitados.
•int tiempo; /* global */
int d[N], f[N], p[N], color[N]; /* Arreglos de tiempo de entrada, tiempo de salida, padres, y color */
•DFS(G) { /* pseudo-código */
for ( cada vértice u  V[G]) {
color [u] =Blanco;
p[u] = NULL;
}
tiempo = 0;
for (cada vértice u  V[G])
if (color[u] == Blanco)
DFS_visit(u);
}
•DFS_visit (u) /* pseudo-código */
color [u]= Gris; /* Vértice Blanco u es visitado, ingresamos a su sub-árbol */
d[u] = ++tiempo; /* el tiempo avanza cada vez que “entramos o salimos” de un nodo*/
for ( cada v  Adj [u] ) { /* explora arcos (u,v) */
if (color [v] == Blanco) { /* v no ha sido visitado */
p [v] = u; /* u es el padre de v, se llegó a v vía u. */
DFS_visit(v);
}
}
color [u] = Negro; /* ennegrezca u, salimos de su sub-árbol */
f [u] = ++tiempo;
}

Tiempo de ejecución: O(|V|+|E|).


Cada arco y nodo es recorrido una vez.
Abstracción
Ordenación topológica
Ejemplo

El ordenamiento no necesariamente es único!

• 5, 7, 3, 11, 8, 2, 9, 10
visual izquierda-derecha, arriba-abajo
• 3, 5, 7, 8, 11, 2, 9, 10
los vértices disponibles de menor número
primero
5, 7, 3, 8, 11, 10, 9, 2
los de menor número de árcos primero
• 7, 5, 11, 3, 10, 8, 9, 2
los vértices disponibles de mayor número
primero
• 5, 7, 11, 2, 3, 8, 9, 10
visual arriba-abajo, izquierda-derecha,
• 3, 7, 8, 5, 11, 10, 2, 9
arbitrario
Abstracción
Ordenación topológica
Ordenar los vértices de un grafo dirigido acíclico (DAG) así:

Si existe un camino entre el nodo v y el nodo w, entonces w


aparecerá después de v

Importante:

No se puede obtener una ordenación topológica de grafos que


contienen ciclos.

Ejemplo:
Identificar los nodos con tareas a realizar entre los cuales hay una
precedencia a la hora de ejecutar dichas tareas

La ordenación topológica es una lista en orden lineal o secuencial


en que deben realizarse las tareas
Abstracción
Ordenación topológica
Ejemplo

El ordenamiento no necesariamente es único!

•v1, v2, v5, v4, v3, v7, v6


•v1, v2, v5, v4, v7, v3, v6
Abstracción
Ordenación topológica

Ejemplo

MAC3311 COP3210 MAD2104 CAP3700 COP3400 COP3337 COP4555


MAD3305 MAD3512 COP3530 CDA4101 CDA4400 COP4540 CIS4610
COP4610 COP5621 COP4225
Abstracción Ordenación topológica –
algoritmo inicial

1. Calcular la propiedad grado de entrada (in-degree) de


todos los vértices del grafo

2. Imprimir los vértices cuyo grado de entrada sea 0

3. Eliminar los vértices que se acaban de imprimir

2. Volver al paso 1

¿Qué pasa con los grados de entrada de los demás


vértices?
Abstracción
Ordenación topológica –
algoritmo mejorado

1. Calcular la propiedad grado de entrada (in-degree) de


todos los vértices del grafo

2. Poner todos los vértices cuyo grado de entrada sea 0


en una colección

3. Imprimir y eliminar uno de los vértices almacenado en


dicha colección

4. Decrementar los grados de entrada de los nodos


adyacentes al vértice eliminado

5. Volver al paso 2
Abstracción Ordenación topológica –
pseudocódigo

void topsort() throwsCycleFoundException {

for ( int counter = 0; counter < NUM_VERTICES; counter++ )


{
Vertex v = findNewVertexOfIndegreeZero();

if ( v == null )
throw new CycleFoundException();

v.topNum = counter;

for each Vertex w adjacent to v


w.indegree--;
}
}
Abstracción Ordenación topológica – pseudocódigo

Tiempo: O(|E| + |V|)

Usando lista de adyacencia


Abstracción
Ordenación topológica
Ejemplo
Abstracción
Ordenación topológica
Ejemplo
Abstracción
Ordenación topológica
Ejemplo
Abstracción
Ordenación topológica
Ejemplo
Abstracción
Ordenación topológica
Ejemplo
Abstracción
Ordenación topológica
Ejemplo
Abstracción
Ordenación topológica
Ejemplo
Abstracción
Ordenación topológica
Ejemplo
Abstracción
Ordenación topológica
Ejemplo
Abstracción
Ordenación topológica
Ejemplo
Abstracción
Ordenación topológica
Ejemplo
Abstracción
Ordenación topológica
Ejemplo
Abstracción
Ordenación topológica
Ejemplo
Abstracción
Ordenación topológica
Ejemplo
Abstracción
Ordenación topológica
Ejemplo

7 5 6
Abstracción
Ordenación topológica
Ejemplo
Abstracción
Ordenación topológica
Ejemplo
Abstracción Camino más corto

Grafos ponderados:
•Cada arco (vi, vj) tiene un costo asociado ci,j

•El costo de un camino v1 v2…vN es

donde ci,i+1 es el costo de (vi, vi+1).


El costo se conoce como: longitud del camino ponderado

Grafos no ponderados:
La longitud del camino no ponderado simplemente
corresponde al número de arcos en el camino: N –1
Abstracción Camino más corto desde un único nodo
origen

Problema:

Dado un grafo G = (V, E), y un nodo s∈V, encontrar el camino más


corto (ponderado) desde s hasta cualquier otro nodo de G.

Ejemplo:

Planear un viaje en metro


Abstracción Camino más corto desde un nodo
origen
Ejemplo:

• El camino más corto ponderado entre v1 y v6 tiene un costo de 6 y va


desde

v1 a v4 a v7 a v6
• El camino más corto no ponderado entre v1 y v6 es 2
Abstracción Camino más corto desde un nodo
origen

Algoritmo para grafos no ponderados:

Breadth First Search – BFS (búsqueda en anchura)


Abstracción Camino más corto desde un nodo
origen
Algoritmo para grafos no ponderados:
Breadth First Search – BFS (búsqueda en anchura)

• Similar al recorrido en anchura o por niveles en los árboles (level


order)

Pasos:

•Hallar todos los nodos adyacentes al nodo de partida (nivel 1)


•Hallar los nuevos nodos adyacentes a los nodos del nivel 1 (nivel
2)
•Hallar los nuevos nodos adyacentes a los nodos del nivel 2 (nivel
3)

y así sucesivamente

Se puede implementar usando como soporte una cola


Abstracción Camino más corto desde un nodo
origen
Algoritmo para grafos no ponderados

Breadth First Search – BFS (búsqueda en anchura)

Pasos detallados (con el nodo s como punto de partida):

1.Asignar a s una distancia de 0 y encolar s


2. Repetir:

a. Desencolar un nodo v
b. Para todos los nodos u (nodos adyacentes a v), que aún no
hayan sido marcados como alcanzados:

i. Asignar a u la distancia de v + 1
ii. Marcar u como nodo alcanzado desde v
iii. Encolar u
Abstracción Camino más corto desde un nodo
origen
Algoritmo para grafos no ponderados:
Breadth First Search – BFS (Búsqueda en anchura)
Abstracción Camino más corto desde un nodo
origen
Algoritmo para grafos no ponderados:
Breadth First Search – BFS (búsqueda en anchura)
Abstracción Camino más corto desde un nodo
origen
Algoritmo para grafos no ponderados:
Breadth First Search – BFS (Búsqueda en anchura)
Abstracción Camino más corto desde un nodo
origen
Algoritmo para grafos no ponderados:
Breadth First Search – BFS (Búsqueda en anchura)
Abstracción Camino más corto desde un nodo
origen
Algoritmo para grafos no ponderados:
Breadth First Search – BFS (Búsqueda en anchura)
Abstracción Camino más corto desde un nodo
origen
Algoritmo para grafos no ponderados:
Breadth First Search – BFS (Búsqueda en anchura)
Abstracción Camino más corto desde un nodo
origen
Algoritmo para grafos no ponderados:
Breadth First Search – BFS (Búsqueda en anchura)
Abstracción Camino más corto desde un nodo
origen
Algoritmo para grafos no ponderados:
Breadth First Search – BFS (Búsqueda en anchura)
Abstracción Camino más corto desde un nodo
origen
Algoritmo para grafos no ponderados:
Breadth First Search – BFS (Búsqueda en anchura)
Abstracción Camino más corto desde un nodo
origen
Algoritmo para grafos no ponderados:
Breadth First Search – BFS (Búsqueda en anchura)
Abstracción Camino más corto desde un nodo
origen
Algoritmo para grafos no ponderados:
Breadth First Search – BFS (Búsqueda en anchura)
Abstracción Camino más corto desde un nodo
origen
Algoritmo para grafos no ponderados:
Breadth First Search – BFS (Búsqueda en anchura)
Abstracción Camino más corto desde un nodo
origen
Algoritmo para grafos no ponderados:
Breadth First Search – BFS (Búsqueda en anchura)
Abstracción Camino más corto desde un nodo
origen
Algoritmo para grafos no ponderados:
Breadth First Search – BFS (Búsqueda en anchura)
Abstracción Camino más corto desde un nodo
origen
Algoritmo para grafos no ponderados:
Breadth First Search – BFS (Búsqueda en anchura)
Abstracción Camino más corto desde un nodo
origen
Algoritmo para grafos no ponderados:
Breadth First Search – BFS (Búsqueda en anchura)
Abstracción Camino más corto desde un nodo
origen
Algoritmo para grafos no ponderados:
Breadth First Search – BFS (Búsqueda en anchura)
Abstracción Camino más corto desde un nodo
origen
Algoritmo para grafos no ponderados:
Breadth First Search – BFS (Búsqueda en anchura)
Abstracción Camino más corto desde un único nodo
origen

Algoritmo para grafos ponderados:


•El problema se hace más difícil cuando los arcos tienen pesos
diferentes

•Los pesos representan costos diferentes asociados a los arcos

Algoritmo:

Dijkstra
Abstracción Camino más corto desde un único nodo
origen - Dijkstra

Algoritmo para grafos ponderados - Dijkstra :


•Es un algoritmo voraz (greedy algorithm):

•Resuelve el problemas por “etapas” (pasos), haciendo lo


que parece mejor en cada etapa
Abstracción Camino más corto desde un único nodo
origen - Dijkstra

Algoritmo para grafos ponderados - Dijkstra :


•Es un algoritmo voraz (greedy algorithm):

•Resuelve el problemas por “etapas” (pasos), haciendo lo


que parece mejor en cada etapa
Abstracción Camino más corto desde un único nodo
origen - Dijkstra
Dado un grafo dirigido ponderado de N nodos no aislados, sea s el nodo inicial. Un arreglo D
de tamaño N guardará al final del algoritmo las distancias desde s al resto de los nodos.
1.Inicializar todas las distancias en D con un valor infinito relativo ya que son desconocidas
al principio, exceptuando la de s que se inicializa en 0 debido a que la distancia de s a s es
0.
•Sea a = s (a es el nodo actual).
•Se recorren todos los nodos adyacentes de a, excepto los nodos marcados, estos nodos se
llamarán nodos no marcados vi.
1.Para el nodo actual, se calcula la distancia tentativa desde dicho nodo a sus vecinos con
la siguiente fórmula:

dt(vi) = Da + d(a,vi).

Es decir, la distancia tentativa del nodo vi es la distancia que actualmente tiene el nodo en el
arreglo D más la distancia desde el nodo a al nodo vi. Si la distancia tentativa es menor que
la distancia almacenada en el arreglo, se actualiza el arreglo con esta distancia tentativa. Es
decir:
Si dt(vi) < Dvi entonces Dvi = dt(vi)
Se marca como completo el nodo a.
Se toma como próximo nodo actual el de menor valor en D (puede hacerse almacenando los
valores en una cola de prioridad) y se vuelve al paso 3 mientras existan nodos no
marcados.
Al final del algoritmo, D estará completamente lleno.
Abstracción Camino más corto desde un nodo
origen - Dijkstra

Videos ilustrativos

Algoritmo de DIJKSTRA UnadM


Pedro Diaz Romo
https://www.youtube.com/watch?v=g6MGBEJQj5o

Algoritmo de Dijkstra (3) - Teoría de Grafos


Juan Antonio Gomez
https://www.youtube.com/watch?v=S_5W5bImTH4

Algoritmo de Dijkstra - Ejemplo 1


Juan Carlos Méndez
https://www.youtube.com/watch?v=VENf0GXRd6E
Abstracción Camino más corto desde un nodo
origen - Dijkstra
Ejemplo nodo origen s: Penn station
Abstracción Camino más corto desde un único nodo
origen - Dijkstra
Ejemplo nodo origen s: Penn station
Abstracción Camino más corto desde un único nodo
origen - Dijkstra
Ejemplo
Abstracción Camino más corto desde un único nodo
origen - Dijkstra
Ejemplo
Abstracción Camino más corto desde un único nodo
origen - Dijkstra
Ejemplo
Abstracción Camino más corto desde un único nodo
origen - Dijkstra
Ejemplo
Abstracción Camino más corto desde un único nodo
origen - Dijkstra
Ejemplo
Abstracción Camino más corto desde un único nodo
origen - Dijkstra
Ejemplo
Agenda

Abstracción

Implementación
Abstracción Ordenación topológica –
pseudocódigo

void topsort() throwsCycleFoundException {

for ( int counter = 0; counter < NUM_VERTICES; counter++ )


{
Vertex v = findNewVertexOfIndegreeZero();

if ( v == null )
throw new CycleFoundException();

v.topNum = counter;

for each Vertex w adjacent to v


w.indegree--;
}
}
Abstracción Ordenación topológica – pseudocódigo

Ponga en la cola los nodos con grado de


entrada 0

Mientras la cola no esté vacía

Asigne la siguiente posición


al nodo que se saca de la
cola

Actualice (disminuya) los grados


de entrada de los nodos adyacentes
al nodo que salió de la cola

Si el grado de entrada es 0, ponga


el nodo en la cola
Abstracción Complejidad - ordenación topológica

Tiempo: O(|E| + |V|)


Usando lista de adyacencia
Abstracción Camino más corto desde un nodo
origen
Algoritmo para grafos no ponderados:
Breadth First Search – BFS (búsqueda en anchura)

Se inicializa la distancia al nodo origen


como INFINITY
La distancia de s a si mismo es 0
Abstracción Camino más corto desde un nodo
origen
Algoritmo para grafos no ponderados:
Breadth First Search – BFS (búsqueda en anchura)

Se inicializa la distancia al nodo origen


como INFINITY
La distancia de s a si mismo es 0
Abstracción Complejidad - camino más corto desde
un nodo origen
Algoritmo para grafos no ponderados:
Breadth First Search – BFS (búsqueda en anchura)

Tiempo: O(|E| + |V|)

Usando lista de adyacencia


Abstracción Camino más corto desde un único nodo
origen - Dijkstra

Se inicializa cada vértice con distancia


INFINITA y se marca como desconocido
Abstracción Camino más corto desde un único nodo
origen - Dijkstra

Se inicializa la distancia al nodo origen


como 0
Abstracción Camino más corto desde un único nodo
origen - Dijkstra

Mientras que hayan nodos con


distancia desconocida
Abstracción Camino más corto desde un único nodo
origen - Dijkstra

Mientras que hayan nodos con


distancia desconocida
Abstracción Camino más corto desde un único nodo
origen - Dijkstra

1. Seleccionar el nodo v con la


menor distancia desconocida
2. Marcar este nodo como
conocido
3. Actualizar las distancias hacia
sus vecinos (nodos
adyacentes)
Abstracción Complejidad - camino más corto desde
un nodo origen - Dijkstra

• Mantener una cola de prioridad para almacenar los nodos


desconocidos
• Cada etapa requiere un llamado a deleteMin y actualizar
las distancias de los vecinos de ese nodo
• En total, se hace un llamado a actualizar las distancias para
cada arco y un llamado a deleteMin para cada vértice

• Ambas operaciones toman


O(log |V|)
• En total:
O( |E| log |V| + |V| log |V|)
= O(|E| log |V|), |E| > |V|

También podría gustarte