Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Página Nº 1 Grafos
conectado a ellos por una arista), si no lo conoce tomamos nota de todos los vecinos de
p y vamos preguntando a cada vecino si conoce a q, si no lo conoce, tomamos nota de
los vecinos de dicho nodo, y así sucesivamente. Vamos tomando nota de los nodos ya
visitados, para no preguntarles dos veces al mismo nodo. Por lo que al no tener mas
nodo a quien preguntar, indicará dicha situación que los nodos p,q no son conexos. Por
supuesto que si algún vecino posee como vecino a q, querrá decir que los nodos p,q son
conexos.
Los nodos visitados lo vamos registrando en un conjunto de nodos, (no es necesario
usar una lista, puesto que la lista ordena sus elemento y aquí no interesa el orden).
Elegimos cualquier vecino de uno de los nodos del conjunto que no está en el
conjunto. Si no hay entonces q no es conexo con p. Si hay nodos y es q, entonces q si es
conexo con p, y si no es q entonces lo agregamos al conjunto y repetimos.
donde
extender (G, C, q) = si hay s C con vecino r C
si ( r = q) „si‟ sino extender (G, C {r}, q)
sino „no‟.
Página Nº 2 Grafos
Ejemplo Dado el gráfico anterior ver si los nodos 3 y 4 son conexos.
donde
extender (G, {3}, 4) = si hay s C con vecino r C (elijo r=2)
si ( 2 = 4) „si‟ sino extender (G, {3} {2}, 4)
Podemos mejorar el algoritmo para obtener el recorrido de los nodos p,q , en caso de
ser conexos. Para ello mantenemos una función llamada portador, que para cada nodo
C, salvo p, da la arista que la hizo entrar en C. En la primera invocación es vacía ya que
p no entra por ninguna arista, p no tiene portador.
Para poder usar la función portador usaremos un nuevo mecanismo notacional.
La función portador está definida en datos, no por algoritmo como lo veníamos
haciendo. Es decir que siempre que se invocaba f(x), se llamaba a un algoritmo, por
ejemplo la función extender (...). Ahora lo que haremos será definir a la función por
datos. Como en otros tipos de datos necesitamos notación para expresar las operaciones
básicas. Si deseamos asignar a la función un valor para un argumento dado, por ejemplo
f(5) = 4, entonces necesitamos la operación que cambia dicha función para un
argumento dado.
En el ejemplo f(5)=4, puede que f(5) no este definida, o que previamente tenía otro
valor. En realidad estamos queriendo definir una nueva función g que es casi igual que f
y difiere únicamente en la cuestión de g(5): queremos que para g(5) sea 4, pero que para
cualquier x 5 g(x) sea definido solo si f(x) esta definido, y en ese caso g(x) = f(x).
Llamaremos este g como f (5 4).
La definición formal es: “Para una función f con dominio D incluido es un tipo de
datos T, con valores en el tipo de datos U, un objeto x de T y un objeto y de U, f (x y)
es la función g de cuyo dominio es D {x} con g(x) = y, y para todo z x en D,
g(z)=f(z) .”
donde
extender (C,portador, q) =
si hay arista a con P(a) = {s,r} donde s C y r C
si ( r = q) construir ( q, portador ( q a) )
sino extender ( C {r},portador (r a), q)
donde
Página Nº 3 Grafos
construir (q, portador) =
si portador(q) = a existe Nota: El a es genérico... ej f(3)=b entonces a=b
sea P(a) ={p, q}
contestar construir(p, portador),a
sino {}
Si la alternativa “si hay arista a ...” no se da, el algoritmo falla (se cuelga).
Este algoritmo es no determinista también. Su no determinismo afecta el resultado
en el caso de que haya más de un camino entre p y q. (según lo que se elija mostrará el
camino encontrado).
La eficiencia del algoritmo depende de cómo encontramos un nodo que
pertenezca a un conjunto y otro que no pertenezca al mismo conjunto “si hay arista a
con P(a) = {s,r} donde s C y r C”. La eficiencia para ello depende mucho de la
estructura de datos con que representemos el conjunto, así que no podemos saber mucho
de la eficiencia de estos algoritmos antes de ver algo sobre como están realizados.
Algo podemos saber. Sabemos por ejemplo que no va a haber más que n
invocaciones de extender, donde n es el número de nodos en G. Entonces la eficiencia
reside en la de extender.
En definitiva: el algoritmo abstracto puede indicar algo de la eficiencia con que
puede trabajar, pero puede depender mucho de cómo se lo realiza también (de la
estructura de datos empleada).
Página Nº 4 Grafos
I
retorna “b a c” al punto *2
II retorna “b a” al punto I
Sólo importan los puentes, las islas y las dos bandas del río. Pero Euler quería
simplificarlo más. El decía que era un problema del siguiente grafo:
Página Nº 5 Grafos
Y que no importaba si los nodos eran islas u otra cosa. Y se puso a pensar en la
generalidad de esos curiosos objetos, que ahora llamamos grafos, y del problema de
encontrar un camino que pasaba por cada arista y volvía al nodo de partida.
Euler resolvió ese primer problema con que fundó la teoría de grafos.
Resultó que no existía un ciclo de Euler para los puentes de Königsburg. La razón
era que el grafo tiene nodos de grado impar. El grado de un nodo es el número de
extremos de aristas conectados al nodo.
Decimos extremos porque una arista conectado a un solo nodo cuanta pasa dos. La
idea es si imaginamos una puerta en cada extremo de cada arista, para entrar y salir del
nodo, el grado es el número de puertas.
Definición: El grado de un nodo p en un grafo G = (N, A, P) es el número de
aristas a tal que P(a) = {p, q} con q p, más dos veces el número de aristas a tal
que P(a) = {p}.
Teorema: Un grafo sin nodos aislados (nodos sin aristas) tiene un ciclo de Euler
si y solo si es conexo y cada nodo tiene grado par.
Si hay un ciclo de Euler, salimos por una puerta del nodo inicial y entramos en otra
puerta al final de la última arista, y para cada nodo intermedio entramos por una puerta
y salimos por otra (incluimos que el nodo intermedio puede ser un nodo ya visitado,
pero usando otras puertas, tanto para entrar como para salir). Entonces vemos un
número par de puertas en cada nodo. No puede haber una puerta que no pasamos porque
eso significaría una arista que no pasamos.
Conclusión: un ciclo de Euler implica que cada nodo tiene grado par.
El algoritmo empieza con cualquier nodo p de G, y sigue eligiendo aristas hasta que
vuelve a p, pero recordando las aristas elegidas para no usarlas nuevamente.
Luego preguntamos si en el recorrido del ciclo así formado hay un nodo con una
arista que no está en el ciclo:
-Si no hay, no hay ninguna arista sin usar porque el grafo es conexo.
-Si hay, el nodo pertenece al ciclo pero no una arista que lo toca. Entonces el
algoritmo hace un ciclo sobre ese nodo y lo inserta en el lugar en donde está ese nodo,
obteniendo un nuevo ciclo, con que repite lo que estamos haciendo.
Por ejemplo insertamos el ciclo efg en el ciclo abcd.
Página Nº 6 Grafos
La única forma en que este algoritmo puede fallar es en no poder completar un ciclo
sobre un nodo dado. La única forma de que eso ocurra es que llegue a un nodo que no
posea aristas que no fue usada ya. Pero eso no se da con el nodo inicial, porque sería un
nodo sin aristas, un nodo aislado, que no hay. Tampoco se da al iniciar un ciclo para ser
insertado, porque ese nodo está elegido precisamente porque tiene una arista no usada.
Y, finalmente no puede ser un nodo recién entrado porque ha entrado un número impar
de veces, porque cada vez que entró previamente, salió. Pero el grado del nodo es par,
por lo tanto queda por lo menos una puerta sin usar, implicando de una arista sin usar.
donde
extender (c, B) = (c un ciclo, B las aristas no en c)
si (B es vacio) c
sino
sea r un recorrido del camino c
sea a B tal que P(a) = { ri, q} para algún i y nodo q
sea (d, D) = ciclo ({a},ri , q, B –{a})
extender ( insertar (d, c, i), D)
donde
ciclo (c, p, q, B) =
si (p = q) (c, B)
sino
sea a B con P(a) = {q, r}, algún nodo r
ciclo (ca, p, r, B -{a})
insertar(d, c, i) =
si (d es vacia) c
sino insertar (resto(d), c (id1, cj cj-1, todo j > i ), i+1)
donde
** extender ({}, {a,b,c,d,e,f,g}) = (c un ciclo, B las aristas no en c)
c posee aristas
si ({a,b,c,d,e,f,g} es vacio) c
sino
sea r un recorrido del camino c
Nota: en este momento c no tiene camino (aristas), por lo tanto no
habría nodos que unen esas aristas (recorrido del camino son los nodos).
Página Nº 7 Grafos
Pero por definición “ El camino vacio conecta cualquier nodo con si
mismo”, por lo que podemos elegir cualquier nodo.
---------------------------------------------------------
Página Nº 8 Grafos
Nota: Tome una arista que este en B (d) , pero que tenga un nodo igual
a q, en este caso q= 2 por lo que las únicas aristas que tienen al nodo 2
son „d‟ y „a‟. Pero „a‟ B.
--------------------------------------------
Hacemos C1=‟a‟
Página Nº 9 Grafos
invocamos a insertar ({ b}, {a, d, c}, 4) vamos *2-c
responder { a, d, c ,b } regresamos *2-a
-------------------------------------------------------
Página Nº 10 Grafos
responder {a, d, c, g, f, e, b } regresamos a *4-b
2) C x ( abreviatura de C {x})
(s, n) t = si (t (s, n)) (s, n) sino (s(n+1 t), n+1)
nota: s(n+1 t) significa que al vector s le agrego el elemento t en la posición n+1
3) C – x
(s, n) – t = si (hay i con 1 i n, y t = xi ) (s( j sj+1 para i j < n), n-1)
Una vez que encuentro el elemento en la posición i, hago un corrimiento desde el
elemento hacia el final, eliminando el elemento y reduciendo a n-1 el tamaño de s.
j sj+1 significa s[j]= s[j+1] desde j:=i hasta n-1.
2) C x ( abreviatura de C {x})
Página Nº 11 Grafos
agregar (x, s, n)
si (x (s, n))
n = n+1;
sn = x;
3) C – x
sacar(x, s, n)
para (i =1 hasta n)
si ( si = x)
para ( i hasta n-1)
si = si+1;
n = n-1
----------------------------
CAMINO MINIMO
Hay un montón de problemas en que cada arista tiene un costo de algún tipo, como
por ejemplo distancia, o tiempo, o precio del boleto de avión.
Definición: Un grafo con costos es (N, A, P, c) donde (N, A, P) es un grafo y c es
una función de las aristas a los números reales no negativos.
El costo de un camino a1, a2, ......,an es 1 c (ai).
n
Expresemos el algoritmo:
donde
costo1(C, m, d) =
sea a una arista tal que P(a) = {p, q} con p C y q C
y tal que d(p) + c(a) es lomás pequeño posible
si (q = m) d(p) + c(a)
sino costo1(C {q}, m, d(qd(p) + c(a)))
Página Nº 12 Grafos
grafo costos
donde
costo1({1}, 8, { 10}) = costo1(C, m, d)
{ 10} significa que el costo para llegar al nodo 1 es 0
qm
invocamos a costo1({1, 2}, 8, d(10, 20 + 1)) vamos a *1
respondemos 6
qm
invocamos a costo1({1, 2, 3}, 8, d(10, 21, 32)) vamos
a *1-a
respondemos 6 regresamos a *1
48
invocamos a costo1({1, 2, 3, 4}, 8, d(10, 21, 32, 43)) vamos
a *1-b
respondemos 6 regresamos a *1a
68
Página Nº 13 Grafos
invocamos a costo1({1, 2, 3, 4, 6}, 8, d(10, 21, 32, 43, 63)) vamos
a *1-c
respondemos 6 regresamos a *1b
58
invocamos a costo1({1, 2, 3, 4, 6, 5}, 8, d(10, 21, 32, 43, 63, 54))vamos a *1-d
respondemos 6 regresamos a *1c
78
invocamos a costo1({1, 2, 3, 4, 6, 5, 7}, 8, d(10, 21, 32, 43, 63, 54, 75))vamos
a *1e
respondemos 6 regresamos a *1d
*1-e costo1({1, 2, 3, 4, 6, 5, 7}, 8, d(10, 21, 32, 43, 63, 54, 75)) =
elegimos h tal que P(h)= {7, 8} 7 C y 8 C
y d(7) + c(h) = 5 + 1 = 6
si (q = m) d(p) + c(a)
como 8 = 8 d(7) + c(h) = 5 + 1 = 6
respondemos 6 regresamos a *1e
Las siguientes figuras muestran las sucesivas llamadas a costo1. Los nodos con un
número escrito adentro son los que pertenecen a C, y el número es el valor de d para ese
nodo.
Página Nº 14 Grafos
caminoMinimo (n,m)=
si(m = n) { }
sino sacarCamino (nodoArista ( {n}, m, {n0} ))
donde
nodoArista (C, m, d) =
sea a una arista tal que P(a) = {p, q} con p C y q C
y tal que d(p) + c(a) es lo más pequeño posible
si ( q = m) e( qa)
sino nodoArista ( C {q}, m, d( q d(p) + c(a)), e(qa)
donde
sacarCamino (e, n) =
si (e(n) no está definida) {}
sino sea P(e(n))= {n, q} (e(n) siempre está anclada en n por construcción)
sacarCamino(e, q), e(n)
Página Nº 15 Grafos
grafo costos
caminoMinimo (1,5)=
si(5 = 1) { }
sino sacarCamino (nodoArista ( {1}, 5, {10} ), 5) vamos a *1
invocamos a sacarCamino((5 l, 6e, 4c, 3b, 2a), 5) vamos a *2
Respondo: b, e, l
-----------------------------------------
donde
*1 nodoArista ( {1}, 5, {10} ) = nodoArista (C, m, d) =
2 5
invoco a nodoArista ( {1, 2}, 5, d(10, 21)) vamos *1-a
Respondemos e(5 l, 6e, 4c, 3b, 2a) Regresamos a *1
3 5
invoco a nodoArista ( {1, 2, 3}, 5, d(10, 21, 32) ) vamos *1-b
respondemos e(5 l, 6e, 4c, 3b) Regresamos a *1
45
invoco a nodoArista ( {1, 2, 3, 4}, 5, d(10, 21, 32, 43) )vamos
*1-c
respondemos e(5 l, 6e, 4c) Regresamos a *1-a
65
invoco a nodoArista ( {1, 2, 3, 4, 6}, 5, d(10, 21, 32, 43, 63))
vamos *1-d
responder e( 5 l), e (qa)
respondemos e(5 l, 6e) Regresamos a *1-b
Página Nº 16 Grafos
y d(6) + c(l) = 3 + 1 = 4 (es el mínimo)
si ( q = m) e( qa)
5=5 responder e( 5 l) Regresamos a *1-c
(significa que al nodo 5 lo accedemos mediante la arista l)
------------------------------------
donde
*2 sacarCamino((5 l, 6e, 4c, 3b, 2a), 5) = sacarCamino (e, n)
si (e(n) no está definida) { }
sino
sea P(e(n))= {n, q}
como (e(5) = l) P(l) = {5, 6}
Para la red siguiente obtenga el árbol generado por el Router A considerando que
se aplica el algoritmo de Dijkstra. Los números indican el costo del enlace hacia
el vecino correspondiente.
Página Nº 17 Grafos
NOTA RB (10) ----- RE (2) SIGNIFICA QUE PARA IR DE RB A RE EL
COSTO ES 2 Y PARA IR DE RE A RB EL COSTO ES 10.
RESPUESTA:
DIJKSTRA: Inicializa E con el nodo origen, R con el resto de los nodos y O con
los caminos a partir del origen por orden creciente de métrica.
En P ponemos el camino elegido.
E=(RA); R=(RB,RC,RD,RE,RF,RG,RH);
P=( ).
O=(RARB(2),RARD(4), RARE(5)).
Página Nº 18 Grafos
P=( RARB(2), RARD(4)).
Página Nº 19 Grafos
O=( RARBRERH(12), RARBRERFRH(12))
O=( RARBRERFRH(12))
Elijo RARBRERH (RH si se encuentra en E)
Árbol resultante
RA 4
2
RB RD
7 4
RC RE
12 5
6
RH RF RG
Página Nº 20 Grafos