Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Muchos problemas se pueden representar utilizando grafos en los que se le asigna un peso
a cada una de las aristas. Consideremos a modo de ilustración, la forma en que se representa
el sistema de vuelos de una línea aérea. Construimos el modelo básico representando las
ciudades mediante vértices y los vuelos mediante aristas. Los problemas relacionados con
distancias pueden representarse asignándole a las aristas las distancias entre ciudades. En la
figura 1, se presenta el mismo grafo, con diferentes pesos asignados a sus aristas, que
representan distintas problemáticas a resolver. ¿Cuál es el camino mas corto en distancia
aérea entre Boston y Los Ángeles? ¿Qué combinación de vuelos tiene el menor tiempo total
de vuelo entre Boston y Los Ángeles? ¿Cuál es la tarifa más barata entre esas dos ciudades?,
estos y muchos otros problemas pueden ser modelados con grafos ponderados, el algoritmo
de Dijkstra nos será de utilidad para ciertos problemas que impliquen encontrar la
combinación de aristas con pesos menores para poder trazar una trayectoria de nodo a
nodo.
Distancias
Tarifas
El algoritmo fue desarrollado por el físico e informatico Edsger Wybe Dijkstra en 1959 y es
un ejemplo más de algoritmo voraz.
El ejemplo típico de aplicación se presenta cuando estamos, por ejemplo, ante un mapa de
carreteras y se trata de encontrar el camino mas corto entre dos localidades cualesquiera,
midiendo siempre el recorrido siguiendo el criterio de la distancia más corta entre las
localidades, aunque, también se puede representar problemas distinto, como el costo de
cada viaje, o el tiempo de viaje, asignando los valores correspondientes a costo y tiempo, en
las aristas.
En el inicio de la ejecución del algoritmo, a cada vértice u de G se le da una etiqueta L(i) que
indica la mejor estimación actual de la longitud de la ruta mas corta de “a” a “i” L(a)=0 ya
que el camino mas corto de “a” a “a” tiene longitud 0, pero debido a que no existe ninguna
información previa acerca de las longitudes de las trayectorias mas cortas de “a” a cualquier
otro vértice de G, la etiqueta L(i) de cada vértice i diferente de “a” se hace inicialmente igual
al número, que se denota por ∞, que es mayor que la suma de los pesos de todas las aristas
de G. Como la ejecución de los progresos de algoritmo, se cambian los valores de L(i),
convirtiéndose en las longitudes reales de las trayectorias más cortas, de “a” a “i” en G.
Porque t se construye hacia el exterior desde “a” en cada etapa de ejecución del algoritmo,
los únicos vértices que son candidatos a formar parte de t son los que están junto al menos
un vértice de t. así en cada etapa del algoritmo de Dijkstra el grafo G puede pensarse como
dividido en 3 partes:
El árbol t que se está construyendo en el conjunto de vértices marginales que son adyacentes
al menos a un vértice del árbol y el resto de los vértices de G. cada franja de vértices es un
candidato hacia el siguiente vértice, agregado t. el elegido es aquel para que la longitud de
la trayectoria más corta de “a” a t es un mínimo entre todos los vértices de la franja.
10 b
a
5
9
3 c
f
8
5 4
15
e 2 d
Asignamos distancia 0 para ir de “a” a “a”, es decir, L(a)=0 y L(i)=∞ para el resto de los nodos. La
distancia al nodo “a” de partida llevará la, etiqueta p indicando así que tal distancia ya será
permanente durante las primeras etapas del algoritmo. Las distancias al resto de nodos serán ∞ y
temporales t.
𝑐(𝑃) = ∑ 𝑐(𝑎)
𝑎∈𝐴(𝑃)
Sea mínimo.
Pseudocódigo. Dijkstra
Entrada: G [un grafo conexo simple con un peso positivo para cada arista], ∞ [un número mayor que
la suma de los pesos de todas las aristas del grafo], 𝑤(𝑢, 𝑣) [el peso de la arista {𝑢, 𝑣}], 𝑎 [El vértice
inicial], 𝑧 [el vértice final].
1.- Inicializa G como el grafo con el vértice a y sin aristas. Sea V(G) el conjunto de los vértices de G y
sea A(G) el conjunto de aristas de G.
2.- Sea L(a)=0 y para todos los vértices en G excepto a, sea L(u) = ∞ . [el número L(x) se llama etiqueta
de x].
3.- Inicialice v a igual a y F será {a}. [El símbolo v se utiliza para denotar el vértice agregado a G].
[El conjunto F se llama la franja. Cada vez que se agrega un vértice a G, se elimina de la franja
y se agregan los vértices adyacentes a la franja si ya no están en la franja o en el árbol G].
𝐷(𝑢) ≔ 𝑣
end while
Salida: 𝐿(𝑧) [𝐿(𝑧) es un numero entero no negativo, es la longitud de la trayectoria más corta de a a
z].
Para ilustrar mejor el mecanismo de acción del algoritmo, veremos un ejemplo por pasos
para encontrar la ruta mas corta de a a z.
Solución
Durante la iteración:
Durante la iteración:
Paso 3: Va al bucle 𝑤ℎ𝑖𝑙𝑒: 𝑉(𝐺) = {𝑎, 𝑏, 𝑐}, 𝐴(𝐺) = {(𝑎, 𝑏), (𝑎, 𝑐)}
Durante la iteración:
𝐹 = {𝑑, 𝑒}, 𝐿(𝑑) = 9, 𝐿(𝑒) = 5, 𝐿(𝑒) = 5
𝐿(𝑒)𝑠𝑒 ℎ𝑎𝑐𝑒 5 𝑝𝑜𝑟𝑞𝑢𝑒 𝑎 − 𝑐 − 𝑒, 𝑞𝑢𝑒 𝑡𝑖𝑒𝑛𝑒
𝑙𝑜𝑛𝑔𝑖𝑡𝑢𝑑 5, 𝑒𝑠 𝑢𝑛𝑎 𝑡𝑟𝑎𝑦𝑒𝑐𝑡𝑜𝑟𝑖𝑎 𝑚á𝑠 𝑐𝑜𝑟𝑡𝑎
𝑎 𝑒 𝑞𝑢𝑒 𝑎 − 𝑏 − 𝑒, 𝑞𝑢𝑒 𝑡𝑖𝑒𝑛𝑒 𝑙𝑜𝑛𝑔𝑖𝑡𝑢𝑑 8.
𝑌𝑎 𝑞𝑢𝑒 𝐿(𝑒) < 𝐿(𝑑), 𝑒 𝑠𝑒 𝑎𝑔𝑟𝑒𝑔𝑎 𝑎 𝑉(𝐺) 𝑦
(𝑐, 𝑒)𝑠𝑒 𝑎𝑔𝑟𝑒𝑔𝑎 𝑎 𝐴(𝐺).
Paso 4: Va al bucle 𝑤ℎ𝑖𝑙𝑒: 𝑉(𝐺) = {𝑎, 𝑏, 𝑐, 𝑒}, 𝐴(𝐺) = {(𝑎, 𝑏), (𝑎, 𝑐), (𝑐, 𝑒)}
Durante la iteración:
𝐹 = {𝑑, 𝑧}, 𝐿(𝑑) = 7, 𝐿(𝑧) = 17
𝐿(𝑑)𝑠𝑒 ℎ𝑎𝑐𝑒 7 𝑝𝑜𝑟𝑞𝑢𝑒 𝑎 − 𝑐 − 𝑒 − 𝑑, 𝑞𝑢𝑒
𝑡𝑖𝑒𝑛𝑒 𝑙𝑜𝑛𝑔𝑖𝑡𝑢𝑑 7, 𝑒𝑠 𝑢𝑛𝑎 𝑡𝑟𝑎𝑦𝑒𝑐𝑡𝑜𝑟𝑖𝑎 𝑚á𝑠
𝑐𝑜𝑟𝑡𝑎 𝑎 𝑑 𝑞𝑢𝑒 𝑎 − 𝑏 − 𝑑, 𝑞𝑢𝑒 𝑡𝑖𝑒𝑛𝑒 𝑙𝑜𝑔𝑖𝑡𝑢𝑑
9. 𝑌𝑎 𝑞𝑢𝑒 𝐿(𝑑) < 𝐿(𝑧), 𝑑 𝑠𝑒 𝑎𝑔𝑟𝑒𝑔𝑎 𝑎 𝑉(𝐺)
𝑦 (𝑒, 𝑑) 𝑠𝑒 𝑎𝑔𝑟𝑒𝑔𝑎 𝑎 𝐴(𝐺).
Paso 5: Va al bucle 𝑤ℎ𝑖𝑙𝑒: 𝑉(𝐺) = {𝑎, 𝑏, 𝑐, 𝑒, 𝑑}, 𝐴(𝐺) = {(𝑎, 𝑏), (𝑎, 𝑐), (𝑐, 𝑒), (𝑒, 𝑑)}
La ejecución del algoritmo termina en este momento porque 𝑧 ∈ 𝑉(𝐺) . La trayectoria más
corta de 𝑎 a 𝑧 tiene longitud 𝐿(𝑧) = 14.
Siguiendo los pasos en una tabla es una forma conveniente de mostrar la acción del
algoritmo de Dijkstra. La tabla 1 hace esto para el grafo del ejemplo.
El algoritmo de Dijkstra determina la longitud del camino más corto entre dos vértices de
un grafo ponderado simple, conexo y no dirigido.
Podemos estimar la complejidad computacional del algoritmo de Dijkstra (en términos de
sumas y comparaciones). El algoritmo realiza a lo más n-1 iteraciones, ya que en cada
iteración se añade un vértice al conjunto distinguido. Para estimar el número total de
operaciones basta estimar el número de operaciones que se llevan a cabo en cada iteración.
Podemos identificar el vertice con la menor etiqueta entre los que no estan en el conjunto
realizando n-1 comparaciones o menos. Después hacemos una suma y una comparación
para actualizar la etiqueta de cada uno de los vértices. Por lo tanto en cada iteración se
realizan a lo sumo 2(n-1) operaciones, ya que no puede haber más de n-1 etiquetas por
actualizar en cada iteración. Como no se realizan más de n-1 iteraciones cada una de las
cuales supone a lo más 2(n-1) operaciones, llegamos al siguiente teorema: