• No se han encontrado resultados

Grafos con pesos

In document Metodos Python (página 141-143)

15. Cálculo numérico elemental

16.4. Grafos con pesos

salida entrada salida entrada salida

Figura 16.4: Laberinto (izquierda) y solución (centro) usando pila (lifo), y laberinto usando cola fifo (derecha).

sición (usando las funcioneslista.insert(lugar, x),lista.remove(x)o lista.pop(lugar)).

Para los ejemplos del curso no hace diferencia. El módulo estándarcollections implementa listas fifo eficientemente encollections.deque(ver elmanual de la biblioteca). Nosotros no lo veremos en el curso.

b) Repetir elejercicio 16.10, comparando las diferencias entre el recorrido en pro- fundidad y el recorrido a lo ancho.

- En la página del libro se muestra una«película»(archivo pdf ) de cómo se va constru- yendo el árbol. Lafigura 16.3es la última página de ese archivo, destacando el orden en que las aristas se incorporan a él cuando la raíz es 1 (comparar con lafigura 16.2).

¡ Una forma dramática de mostrar las diferencias de recorridos lifo o fifo es constru- yendo laberintos como los de lafigura 16.4.

Estos laberintos se construyen sobre una grilla de m×n de puntos con coordenadas enteras, donde un vértice(i , j ) es vecino del vértice (i0, j0) si |i − i0| + |j − j0| = 1, es decir

si uno está justo encima del otro o al costado.

Se dan numeraciones aleatorias a las listas de vecinos después de construirlas (con

random.shuffle), y la raíz (entrada) se toma aleatoriamente sobre el borde inferior. Fi- nalmente, se construyen los árboles correspondientes usando el algoritmorecorrido. Como se trata de árboles, sabemos que hay un único camino entre cualquier par de vértices. Tomando aleatoriamente un punto de salida sobre el borde superior, podemos construir el único camino entre la entrada y la salida, lo que constituye la «solución» del laberinto.

En lafigura 16.4a la izquierda mostramos el árbol obtenido para cola lifo y a la derecha para cola fifo, para m= n = 20, usando una misma semilla (conrandom.seed) para tener las mismas listas de vecinos. En la parte central de la figura mostramos la «solución» del laberinto a la izquierda (cola lifo).

Observamos una diferencia notable en la calidad de los árboles. El recorrido con cola fifo o ancho primero produce un árbol mucho más «regular». Por supuesto, los árboles tienen la misma cantidad de aristas, pero los caminos obtenidos con recorrido en profundidad primero produce caminos mucho más largos.

16.4. Grafos con pesos

Algunas veces la información interesante de un grafo está en los vértices, y las aristas nos dicen que, por alguna razón, dos vértices están relacionados y nada más. Otras veces, las aristas tienen información adicional que queremos considerar. Por ejemplo si las aristas indican rutas entre ciudades, la información podría ser la distancia entre las ciudades. Cuando cada arista e∈ E de un grafo tiene un costo o peso asociado, we,

Ejemplo de grafo pesado w peso de arista 1 2 3 4 5 6 2 1 1 2 3 8 3 1 2 1 Arista e peso we {1,2} 2 {1,4} 3 {1,5} 8 {2,3} 2 {2,4} 1 {3,4} 1 {3,5} 2 {3,6} 1 {4,6} 1 {5,6} 3

Figura 16.5: Un grafo con pesos en las aristas.

decimos que se trata de un grafo con pesos o pesado. Consideraremos aquí sólo el caso

we> 0 para todo e ∈ E .

En lafigura 16.5vemos un ejemplo de grafo con pesos, marcados con recuadros en las aristas correspondientes, y que por comodidad y claridad reproducimos al costado. Pensando que los vértices representan ciudades y los costos de las aristas repre- sentan distancias, si tuviéramos que ir de una ciudad a otra, teniendo distintas rutas alternativas para elegir, es razonable preguntarse cuál de ellas será la más corta (o la más barata). Éste es el problema del camino más corto: en un grafo pesado, y dados dos vértices s , t∈ V , encontrar un camino (s = v1, v2, . . . , vk= t ) con peso total mínimo, donde el peso total de un camino se define como

w{v1,v2}+ w{v2,v3}+ ··· + w{vk−1,vk}=

k−1

X i=1

w{vi,vi+1}.

Observemos que el valor de k no está fijo: no nos interesa si tenemos que usar una arista o cien, sólo nos interesa que la suma de las distancias para ir de s a t sea mínima.

Por ejemplo, en el grafo de lafigura 16.5podemos usar varios caminos para ir del vértice 1 al 5: el camino(1,5) usa una única arista (k = 2) y tiene peso 8, el camino (1,2,3,5) usa 3 aristas y tiene costo total 2 + 2 + 2 = 6, y en realidad no hay otro con menor costo. Sin embargo, el camino(1,4,3,5) también tiene costo 3+1+2 = 6, es decir, puede haber más de un camino con distancia mínima.

Siguiendo con el ejemplo de las ciudades, otro problema interesante es pensar que inicialmente las ciudades no están unidas, los pesos de las aristas representan ahora los costos de construcción de los caminos correspondientes, y queremos construir carreteras de modo de que todas las ciudades puedan unirse entre sí mediante estas nuevas rutas, pero el costo de la construcción sea lo menor posible.

El problema es entonces encontrar un subconjunto de aristas que, junto con los vértices originales, formen un subgrafo generador conexo, y tal que la suma de los costos de ese subconjunto de aristas sea lo menor posible.

Claro que si el grafo original no es conexo, no podremos encontrar un subgrafo conexo (y generador). Por otro lado, no pueden formarse ciclos porque podríamos sacar del ciclo la arista con mayor costo manteniendo la conexión.

- Este razonamiento es correcto si en el ciclo hay alguna arista con costo estrictamente positivo, pero podríamos tener problemas si tienen costo cero o negativo (nosotros suponemos que todas las aristas tienen costo positivo). Por ejemplo, si hay un ciclo de costo negativo, recorriendo el ciclo reduciremos el costo total, y si lo repetimos muchas veces...

Es decir, queremos un subgrafo generador, conexo y sin ciclos, y por lo tanto el conjunto de aristas a elegir debe forman un árbol generador, que haga mínima la suma

In document Metodos Python (página 141-143)

Documento similar