La descarga está en progreso. Por favor, espere

La descarga está en progreso. Por favor, espere

Grafos Introducción y definiciones.

Presentaciones similares


Presentación del tema: "Grafos Introducción y definiciones."— Transcripción de la presentación:

1 Grafos. 3.1. Introducción y definiciones.
3.2. Representaciones de grafos. 3.3. Problemas y algoritmos sobre grafos. Recorridos sobre grafos. Árboles de expansión. Problemas de caminos mínimos. Algoritmos sobre grafos dirigidos. Puntos de articulación y componentes biconexos. Otros problemas con grafos. 1 Tema Grafos.

2 3.1. Introducción y definiciones.
Ejemplos de grafos. Grafo de transiciones (AFD). Tiempo de vuelos aéreos. b 2 3 Bilbao b Barcelona Coruña 1 inicio a b 2 b 1 1 2 3 Madrid 4 a 6 2 3 Murcia Sevilla a a Planificación de tareas (Pert/CPM). Grafo asociado a un dibujo de líneas (visión artificial). D(2) A(3) inicio C(4) E(1) final B(2) 2 Tema Grafos.

3 3.1. Introducción y definiciones.
Un grafo G es una tupla G=(V, A), donde V es un conjunto no vacío de vértices y A es un conjunto de aristas o arcos. Cada arista es un par (v, w), donde v, w pertenecen a V. Grafo no dirigido: Las aristas no están ordenadas, es decir: (v, w) = (w, v) Grafos dirigidos (o digrafos): Los pares sí están ordenados: <v, w>  <w, v> <v, w>  v = cabeza de la arista, w = cola de la arista Un vértice w es adyacente a v sí y sólo si (v, w) (ó <v, w>) pertenece a A. Camino de un vértice w1 a wq: es una secuencia w1, w2, ..., wq  V, tal que todas las aristas (w1, w2), ..., (wq-1, wq)  A. Longitud de un camino: número de aristas del camino = nº de nodos -1 Camino simple: aquel en el que todos los vértices son distintos (excepto el primero y el último que pueden ser iguales). v w v w 3 Tema Grafos.

4 3.1. Introducción y definiciones.
Ciclo: es un camino en el cual el primer y el último vértice son iguales. Se llama ciclo simple si el camino es simple. En grafos no dirigidos es necesario que las aristas sean diferentes. Dados dos vértices v, w, se dice que están conectados si existen un camino de v a w. Un grafo es conexo (o conectado) si hay un camino entre cualquier par de vértices. Si es un grafo dirigido se llama fuertemente conexo. Un grafo es completo si existe una arista entre cualquier par de vértices. Para n nodos, ¿cuántas aristas tendrá el grafo? Grado de un vértice v: número de arcos que inciden en él. Para grafos dirigidos, grado de entrada: nº de aristas con <x, v>; grado de salida: nº de aristas con <v, x>. Un grafo está etiquetado si asociamos a cada arista un peso o valor. Grafo con pesos: grafo etiquetado con valores numéricos. Un subgrafo de G=(V, A) es un grafo G’=(V’, A’) tal que V’V y A’A. 4 Tema Grafos.

5 3.2. Representación de grafos.
Representación mediante matrices de adyacencia. El conjunto de aristas es representado mediante una matriz M[nodo, nodo] de booleanos, donde M[v, w]= 1 sí y sólo si (v, w)  A. Si el grafo está etiquetado, la matriz será de elementos de ese tipo, por ejemplo, caracteres o enteros. Tomará un valor nulo si no existe ese arco. 7 1 2 2 -1 3 3 3 4 5 4 Si el grafo es no dirigido, M[v, w] = M[w, v]. La matriz es simétrica. Problemas. Si el número de nodos es muy grande y hay poca conectividad (pocos arcos, en relación al máximo posible) se desperdicia memoria. Debemos conocer los tamaños aproximados que van a tener los grafos. ¿Cómo se calcularía el grado de entrada o de salida de un nodo? 5 Tema Grafos.

6 3.2. Representación de grafos.
Representación mediante listas de adyacencia. Para cada nodo de V tendremos una lista de aristas que parten de ese nodo. Estas listas están guardadas en un array de nodos cabecera. 2 3 1 2 3 5 3 1 4 5 4 5 4 Grafo etiquetado: añadir un nuevo campo a los elementos de la lista. Si el grafo es no dirigido entonces cada arista (v, w) será representada dos veces, en la lista de v y en la de w. En grafos dirigidos. Calcular el grado de salida: recorrer la lista correspondiente. Grado de entrada: recorrer todas las listas. Otra posibilidad: tener otra lista con las aristas que llegan a un nodo dado. La mejor representación dependerá de las características del problema. 6 Tema Grafos.

7 3.2. Representación de grafos.
Suponer que tenemos n nodos y a aristas. ¿Que implementación será mejor para las operaciones: calcular el grado de entrada o de salida, contar el número de aristas, insertar una arista? Si cada puntero ocupa k1 bytes y cada etiqueta de arista k2 bytes, ¿qué representación ocupará menos memoria? Operaciones típicas sobre grafos: Crear un grafo vacío. Añadir, modificar o borrar un nodo o una arista de un grafo. Combinar dos grafos en uno nuevo. Construir un grafo a partir de otra estructura, p. ej. a partir de una expresión regular, o de una lista de carreteras entre ciudades. Consultar si entre dos nodos existe un arco, y la etiqueta asociada. Obtener el conjunto de nodos a los cuales se llega desde un nodo dado (o bien los nodos que llegan al nodo dado). Recorrer los nodos del grafo siguiendo las aristas en determinado orden. Comprobar si existen ciclos en el grafo, si existen caminos entre determinados nodos. Si el grafo tiene pesos calcular cuales son los caminos de menor costo total. Comprobar si dos grafos son iguales (isomorfos), o uno es subgrafo del otro. 7 Tema Grafos.

8 3.3. Problemas y algoritmos sobre grafos.
Recorridos sobre grafos. Igual que los recorridos en árboles, se parte de un nodo dado y sirven para visitar los vértices y los arcos de manera sistemática. Existen dos tipos de recorridos: Búsqueda primero en profundidad. Es equivalente a un recorrido en preorden de un árbol. Se elige un nodo v de partida. Se marca como visitado y se recorren los nodos no visitados adyacentes a v, usando recursivamente la búsqueda primero en profundidad. Búsqueda primero en amplitud o anchura. Es equivalente a recorrer un árbol por niveles. Dado un nodo v, se visitan primero todos los nodos adyacentes a v, luego todos los que están a distancia 2 (y no visitados), a distancia 3, y así sucesivamente hasta recorrer todos los nodos. El recorrido puede ser para grafos dirigidos o no dirigidos. En los dos casos es necesario llevar una cuenta de los nodos visitados. procedure BorraMarcas; var v: integer; begin for v:= 1 to num_nodos do marca[v]:= no_visitado; end; var marca: array [1..num_nodos] of (visitado, no_visitado); 8 Tema Grafos.

9 3.3.1. Recorridos sobre grafos.
Búsqueda primero en profundidad procedure BuscaPrimeroProfundidad; var v: integer; begin BorraMarcas; for v:= 1 to num_nodos do if marca[v]= no_visitado then bpp (v); end; procedure bpp (v: nodo); var w: integer; begin marca[v]:= visitado; for cada nodo w adyacente a v do if marca[w]= no_visitado then bpp(w); end; El orden en el que se visitan unos nodos a partir de otros puede ser visto como un árbol: árbol abarcador en profundidad asociado al grafo. Si el grafo es no dirigido, entonces se generará un árbol por cada componente conexa. Tendremos un bosque abarcador en profundidad. Grafo no dirigido, no conexo Bosque abarcador en profundidad 1 2 3 4 5 6 7 9 8 1 7 2 8 Arcos del árbol 4 6 9 9 Tema Grafos. 3 5

10 Búsqueda primero en profundidad BPP
10 Tema Grafos.

11 Búsqueda primero en Anchura BPA
Recorrido Arbol por capas 1 2,3 4,6 5 1,2,3,4,6,5 7 8,9 7,8,9 Resultado 1,2,3,4,6,5,7,8,9 11 Tema Grafos.

12 3.3.1. Recorridos sobre grafos.
Búsqueda primero en profundidad Grafo dirigido Bosque abarcador en profundidad b c a b Arco de retroceso Arco de cruce c Arco de avance e d d a e Ejemplo: Prueba de aciclicidad. Dado un grafo (dirigido o no dirigido) comprobar si tiene ciclos o no. Grafo no dirigido. Realizar una búsqueda primero en profundidad. Si aparece algún arco que no es del árbol entonces existe un ciclo. Grafo dirigido. Realizar una búsqueda primero en profundidad. Si aparece algún arco de retroceso entonces existe un ciclo. Orden de complejidad del recorrido en profundidad. Con listas de adyacencia, se recorre cada elemento de lista una vez, O(a+n). Con matrices de adyacencia, para cada nodo se buscan sus adyacentes, O(n2). 12 Tema Grafos.

13 3.3.1. Recorridos sobre grafos.
Búsqueda primero en profundidad ¿Cómo comprobar si un arco es de avance, retroceso o cruce? Solución: Al hacer el recorrido construir explícitamente el árbol de expansión, usando una estructura de punteros al padre. marca: array [1..num_nodos] of integer; marca[v] valdrá: -1 si v no está visitado; 0 si está visitado y es raíz de un árbol; en otro caso indicará cual es el padre de v. Modificar los procedimientos BorraMarcas, BuscaPrimeroProfundidad y bpp, para construir el árbol. Arco de avance <v, w>: w es hijo de v en uno de los árboles del bosque. Arco de retroceso <v, w>: v es hijo de w. Arco de cruce <v, w>: v y w están en distintos árboles. Búsqueda primero en amplitud o anchura Se comienza por un vértice elegido v. Se visitan todos sus adyacentes. Luego los adyacentes de estos y así sucesivamente. Para ello se utiliza una cola de vértices. Operaciones básicas: Sacar un elemento de la cola. Añadir sus adyacentes a la cola (si no están visitados). 13 Tema Grafos.

14 3.3.1. Recorridos sobre grafos.
Búsqueda primero en amplitud o anchura procedure bpa (v: nodo); var C: Cola(nodo); x, y: nodo; begin marca[v]:= visitado; InsertaCola(v, C); while not EsVacíaCola(C) do begin x:= FrenteCola(C); SuprimirCola(C); for cada nodo y adyacente a x do if marca[y]=no_visitado then begin marca[y]:= visitado; InsertaCola(y, C); end; procedure BuscaPrimeroAnchura; { Igual que BuscaPrimeroProfundidad} var v: nodo; begin BorraMarcas; for v:= 1 to num_nodos do if marca[v]= no_visitado then bpa (v); end; a b c e d ¿Cuál es el orden de complejidad del algoritmo? ¿Cómo comprobar de qué tipo son los arcos que no son del árbol? 14 Tema Grafos.

15 3.3.2. Árboles de expansión. Algoritmo de Prim
Definición: Un árbol de expansión de un grafo no dirigido G=(V, A) y conexo es un subgrafo G’=(V, A’) no dirigido, conexo y sin ciclos. Ejemplo: si el grafo ND es conexo, el árbol abarcador (en profundidad o anchura) es un árbol de expansión. Si el grafo es ponderado, el coste del árbol de expansión será la suma de los costes de las aristas. Problema del árbol de expansión de coste mínimo: Dado un grafo ponderado no dirigido, encontrar el árbol de expansión de menor coste. Algoritmo de Prim Escoger un vértice cualquiera v. El árbol consta sólo del nodo v. Del resto de vértices, buscar el que esté más próximo a v (con una arista (w, v) de mínimo costo). Añadir w y la arista (w, v) al árbol. Buscar el vértice más próximo a cualquiera de estos dos, añadir ese vértice y la arista al árbol de expansión. Así sucesivamente hasta haber añadido los n vértices. 15 Tema Grafos.

16 3.3.2. Árboles de expansión. Algoritmo de Prim
El algoritmo maneja los siguientes conjuntos: V: conjunto de vértices del grafo. U: conjunto de vértices seleccionados para el árbol en un momento dado. V-U: conjunto de vértices que quedan por coger. Para calcular el siguiente vértice a coger se usan dos arrays: MAS_CERCANO: Para cada vértice de V-U indica el vértice de U que se encuentra más próximo. MENOR_COSTO: Indica el costo de la arista más cercana (almacenada en el array anterior). Estructura del algoritmo de Prim Inicialmente U={1}  MAS_CERCANO[v] = 1. MENOR_COSTO[v] = C[1, v] Suponemos que C[v, w] (Matriz de costes) contiene el coste de la arista (v, w) Buscar el valor v, con valor MENOR_COSTO mínimo. Asignarle un valor muy grande (para no volver a cogerlo). Recalcular los valores MAS_CERCANO y MENOR_COSTO de los demás nodos. Para cada w, comprobar si C[v, w] es menor que MENOR_COSTO[w]. Repetir los dos puntos anteriores hasta que se hayan añadido los n vértices. 16 Tema Grafos.

17 3.3.2. Árboles de expansión. Algoritmo de Prim
Resultados del algoritmo: Árbol de expansión: las aristas serán los pares (i, MAS_CERCANO[i]), para i= 2, ..., n. Costo del árbol de expansión: Suma de los MENOR_COSTO[i], para i= 2, ..., n (antes de asignarles un valor grande). Ejemplo. Mostrar la ejecución del algoritmo de Prim para el siguiente grafo no dirigido. 5 1 4 1 4 1 1 6 5 2 2 5 3 5 4 3 2 4 2 6 6 6 3 6 3 5 5 ¿Cuál es el orden de complejidad del algoritmo? 17 Tema Grafos.

18 Algoritmo de Prim 18 Tema Grafos.

19 3.3.2. Árboles de expansión. Algoritmo de Kruskal
Dado un grafo ponderado G=(V, A), el algoritmo parte de un grafo G’= (V, Ø). Cada nodo es una componente conexa en sí misma. En cada paso de ejecución se elige la arista de menor costo de A. Si une dos nodos que pertenecen a distintas componentes conexas entonces se añade al árbol de expansión G’. En otro caso no se coge, ya que formaría un ciclo en G’. Acabar cuando G’ sea conexo: cuando tengamos n-1 aristas. Estructura del algoritmo de Kruskal Sea T de tipo Conjunto de aristas, el lugar donde se guardarán las aristas del árbol de expansión. Asignar T a Ø. Mientras T contenga menos de n-1 aristas hacer: Elegir la arista (v, w) de A con menor costo. Borrar (v, w) de A (para no volver a cogerla). Si v, w están en distintos componentes conexos entonces añadir (v, w) a T. En otro caso, descartar (v, w). 19 Tema Grafos.

20 3.3.2. Árboles de expansión. Algoritmo de Kruskal
Ejemplo. Mostrar la ejecución del algoritmo de Kruskal. 5 1 4 1 4 1 4 1 6 1 5 2 2 5 3 4 3 5 3 2 2 4 2 6 6 6 6 3 6 3 5 5 5 Necesidades del algoritmo: Las aristas deben ser ordenadas, según el coste. Necesitamos operaciones para saber si dos nodos están en la misma componente conexa y para unir componentes. Relación dos nodos pertenecen a una componente conexa: es una relación binaria de equivalencia  podemos usar la estructura de representación para relaciones de equivalencia (con operaciones Inicia, Encuentra y Unión). ¿Cuál es el orden de complejidad del algoritmo? 20 Tema Grafos.

21 Algoritmo de Kruskal 21 Tema Grafos.

22 3.3.3. Problemas de caminos mínimos.
Definición: Dado un grafo ponderado G= (V, A) (dirigido o no) y un camino w1, w2, ..., wq en G, el costo del camino será la suma de los costos asociados a las aristas (w1, w2), ..., (wq-1, wq). Si el grafo es no ponderado, normalmente el costo se asocia con la longitud del camino. Problema de los caminos más cortos por un origen: Encontrar los caminos más cortos entre un nodo origen dado y todos los demás nodos. Algoritmo de Dijkstra Supongamos un grafo ponderado G (con pesos  0) y un nodo origen v. El algoritmo trabaja con dos conjuntos: S: conjunto de nodos escogidos, para los cuales se conoce el camino de distancia mínima al origen. C: conjunto de nodos candidatos, pendientes de calcular el camino mínimo. Conocemos los caminos mínimos al origen pasando por nodos de S. En cada paso coger del conjunto de candidatos el nodo con distancia mínima al origen. Recalcular los caminos de los demás candidatos pasando por el nodo cogido. 22 Tema Grafos.

23 3.3.3. Problemas de caminos mínimos.
Algoritmo de Dijkstra Un camino especial del origen a otro nodo cualquiera es un camino que sólo pasa por nodos ya escogidos. Supongamos que el nodo origen es el 1. En un array D[2, ..., N] se guarda la longitud del camino especial más corto a cada vértice. Cuando todos los nodos estén en S, todos los caminos son especiales y D contiene las distancias mínimas al origen. En otro array P[2, ..., N] se almacena el camino por el que pasa cada nodo v. El camino de 1 a v pasa por P[v]. Inicialmente D contendrá los caminos directos de 1 a los restantes nodos, es decir C[1, x]. Si no existe la arista (1, x) el costo será  P contendrá el valor 1 (el camino es directo). S contendrá sólo el nodo 1. Buscar el nodo v de C=V-S con mínimo valor de D. Añadir v a S. Para el resto de nodos comprobar si el camino al origen es más corto pasando por el nodo v. if D[v]+C[v, w] < D[w] then begin D[w]:= D[v] + C[v, w]; P[w]:= v; end; 23 Tema Grafos.

24 3.3.3. Problemas de caminos mínimos.
Algoritmo de Dijkstra procedure Dijkstra; var i: integer; S: array [2..N] of boolean; begin for i:= 2 to N do begin S[i]:= false; D[i]:= C[1, i]; P[i]:= 1; end; for i:= 1 to N-1 do begin v:= vértice con D[v] mínimo y S[v]=false; S[v]:= true; for cada nodo w adyacente a v do if S[v]=false then if D[v]+C[v, w]<D[w] then begin D[w]:= D[v]+C[v, w]; P[w]:= v; var S: array [2..N] of boolean; { Nodos conocidos } D: array [2..N] of integer; { Costos de los caminos } P: array [2..N] of integer; { Camino de 1 a v } C: array [1..N, 1..N] of integer; { Matriz de costos de todas las aristas } procedure ImprimeCamino (v: integer); begin if v<>1 then ImprimirCamino(P[v]); write(v); end; 24 Tema Grafos.

25 3.3.3. Problemas de caminos mínimos.
Algoritmo de Dijkstra Ejemplo: Mostrar la ejecución del algoritmo de Dijkstra sobre el siguiente grafo dirigido. 2 1 2 4 1 3 10 2 3 4 2 5 8 5 4 6 6 7 1 25 Tema Grafos.

26 3.3.3. Problemas de caminos mínimos.
Algoritmo de Dijkstra Orden de complejidad del algoritmo, con matrices de adyacencia: Inicialización: O(n). Ejecutar n-1 veces: Buscar el elemento con D[v] mínimo y S[v] falso: O(n). Actualizar los valores de los nodos candidatos: O(n). En total tenemos O(n2). Con listas de adyacencia: La actualización de los candidatos se limita a los nodos que son adyacentes a v. En total la actualización se hace O(a) veces. La búsqueda del elemento sigue requiriendo O(n) pasos, por lo que el orden total sería O(n2). Podemos usar una estructura ordenada para guardar los nodos candidatos (por ejemplo un árbol binario). La búsqueda requiere O(log n) en cada paso, en total O(n*log n). Además, en la actualización un nodo podría cambiar de posición en el árbol, luego requiere O(a*log n). En total, requiere O((a+n)*log n). Si el grafo es conexo: O(a*log n). Esta modificación será adecuada cuando a<<n2. 26 Tema Grafos.


Descargar ppt "Grafos Introducción y definiciones."

Presentaciones similares


Anuncios Google