Tópicos I - PowerPoint PPT Presentation

slide1 n.
Download
Skip this Video
Loading SlideShow in 5 Seconds..
Tópicos I PowerPoint Presentation
play fullscreen
1 / 118
Tópicos I
246 Views
Download Presentation
feoras
Download Presentation

Tópicos I

- - - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript

  1. Unidad I Tópicos I Árboles, montículos y grafos Semana 4 Algoritmos sobre grafos elementales, Conectividad y Grafos ponderados

  2. Objetivos Generales Entender el manejo, uso de algoritmos y estructuras de datos avanzados, haciendo énfasis en los algoritmos de internet, seguridad y redes.

  3. Objetivo Específico Implementar algoritmos utilizando estructura de datos avanzadas.

  4. Objetivo Instruccional Implementar algoritmos fundamentales para la solución de problemas basados en la teoría de grafos.

  5. Glosario A Grafo: Un grafo es una colección de vértices y aristas. Los vértices son objetos simples que pueden tener un nombre y otras propiedades; una arista es una conexión entre dos vértices. Camino: Un camino entre los vértices x e y de un grafo es una lista de vértices en la que dos elementos sucesivos están conectados por aristas del grafo. B C G D E Algoritmos sobre grafos elementales F A B G E F

  6. Glosario A Grafo conexo: Un grafo es conexo si hay un camino desde cada nodo hacia otro nodo del grafo. Grafo no conexo: Esta constituido por componentes conexos. Camino simple: Es un camino en el que no se repite ningún vértice. Ciclo: es un camino simple con la característica de que el primero y el ultimo vértices son el mismo. B C G D E Algoritmos sobre grafos elementales G A F B D E A F B G E A G F E F

  7. Glosario A Grafo completo: Son los grafos con todas las aristas posibles. Grafo disperso: Tienen relativamente pocas aristas. Grafo denso: Les falta muy pocas aristas de todas las posibles. G Algoritmos sobre grafos elementales E F A G E F A G E F

  8. Representación A Matriz de adyacencia: La matriz de adyacencia solo es satisfactoria si los grafos a procesar son densos. B C G D E Algoritmos sobre grafos elementales F Se construye un array de V*V valores booleanos en el que a[x][y] es igual a 1 si existe una arista desde el vértice x al y, y a 0 en el caso contrario. Es de destacar que en realidad cada arista se representa con dos bits: una arista que enlace x e y se representa con valores verdaderos tanto en a[x][y] como en a[y][x].

  9. Representación A Lista de adyacencia: La lista de adyacencia se adapta mejor a lo casos en los que los grafos a procesar no son densos. B C G D E Algoritmos sobre grafos elementales F A A F A E D A F B F D E C G E G

  10. Recorridos en un grafo En una gran cantidad de problemas con grafos, es necesario visitar sistemáticamente los vértices y aristas del grafo. La búsqueda en PROFUNDIDAD y en AMPLITUD, son dos técnicas importantes de recorrido del grafo. Algoritmos sobre grafos elementales

  11. Búsqueda en Profundidad (BEP) Se comienza en el vértice inicial (vértice con índice 1) que se marca como vértice activo. Hasta que todos los vértices hayan sido visitados, en cada paso se avanza al vecino con el menor índice siempre que se pueda, pasando este a ser el vértice activo. Cuando todos los vecinos al vértice activo hayan sido visitados, se retrocede al vértice X desde el que se alcanzó el vértice activo y se prosigue siendo ahora X el vértice activo. Algoritmos sobre grafos elementales

  12. a b a b a b c c c d e d e d e a b a b a b c c c d e d e d e Búsqueda en Profundidad Algoritmos sobre grafos elementales La estructura utilizada para guardar los nodos a visitar en este tipo de búsqueda es una pila o stack (de procedimiento recursivo).

  13. Búsqueda en Amplitud (BEA) Se comienza en el vértice inicial (vértice con índice 1) y se marca como vértice activo, a diferencia con la BEP ahora se visitan en orden creciente de índice todos los vecinos del vértice activo antes de pasar al siguiente. Hasta que todos los vértices hayan sido visitados, en cada paso se van visitando en orden creciente de índice todos los vecinos del vértice activo. Cuando se han visitado todos los vecinos del vértice activo, se toma como nuevo vértice activo el primer vértice X visitado después del actual vértice activo. Algoritmos sobre grafos elementales

  14. 1 0 0 a b a b 1 c c 1 d e d e 1 0 a b 1 c 2 1 d e Búsqueda en Amplitud Algoritmos sobre grafos elementales En la búsqueda en amplitud se utiliza una cola para guardar tales nodos a visitar.

  15. Usos de los Recorridos • Ambos recorridos se pueden usar para resolver los siguientes problemas: • Probar que G es conectado. • Obtener un árbol de expansión de G. • Obtener los componentes conectados de G. • Obtener un camino entre dos vértices dados de G, o indicar que no existe tal camino. • El recorrido BEP se usa para: • Obtener un ciclo en G, o indicar que G no tiene ciclos. • El recorrido BEA se usa para: • Obtener para cada vértice v de G, el número mínimo de aristas de cualquier camino entre s y v. Algoritmos sobre grafos elementales

  16. Laberintos La búsqueda en profundidad fue expuesta formalmente como un método para recorrer laberintos. El grafo se construye colocando un vértice en cada punto en el que existe mas de un camino a tomar y a conectar a continuación los vértices de acuerdo con esos caminos. Algoritmos sobre grafos elementales “La búsqueda en profundidad es apropiada para la búsqueda de un elemento en el laberinto por una sola persona, dado que el “siguiente lugar a visitar” esta siempre próximo; la búsqueda es amplitud es mas apropiada par un grupo de personas que buscan el mismo elemento desplazándose en todas las direcciones a la vez”

  17. Problemática A Se examinara una generalización de la conectividad denominada biconectividad, cuyo interés reside en conocer si hay mas de un medio de pasar de un vértice de un grafo a otro. G Grafo biconexo: Un grafo es biconexo, si solo si, existen al menos dos caminos diferentes que conecten cada par de vértices. De esta forma si se suprime un vértice y todas las aristas que inciden en el, el grafo permanece conexo. Conectividad E F “Si para algunas aplicaciones es importante que un grafo sea conexo, es también importante que permanezca conexo”

  18. Problemática Una versión particular del problema de la conectividad, que con frecuencia concierne a la situación dinámica en las que las aristas se añaden al grafo una a una, intercalando preguntas sobre si dos vértices determinados pertenecen (o no) a la misma componente conexa. El problema se denomina a veces como “unión-pertenencia”. Conectividad

  19. A B E A B E C D C D Componentes conexas • De un grafo no dirigido • Se pude saber si es conexo • Si no lo es se pueden conocer sus • Componentes Conexas • Conjunto W, de vértices del grafo • En el cual hay camino desde cualquier V1 a cualquier V2 • Donde V1 y V2 pertenecen a W Componentes conexas: entre ellas son conexas Conectividad CONEXO No CONEXO

  20. Biconectividad A A veces es útil diseñar mas de una ruta entre puntos de un grafo, aunque solo sea para identificar posibles fallos en los puntos de conexión (vértices). Esto nos permitiría tener recorridos alternativos por ejemplo para llegar de una ciudad a otra. G Conectividad E F

  21. Puntos de articulación Un punto de articulación en un grafo conexo es un vértice que si se suprime romperá el grafo en dos o mas piezas. En un grafo no dirigido conexo: • Existen vértices que si se eliminan • “Desconectan” al Grafo • Lo dividen en componentes conexas • Estos vértices “clave” son puntos de articulación • Si un grafo no tiene Punto de Articulación • Es biconexo • La conectividad de un grafo • Es el numero de nodos que se necesitan eliminar para dejar a un grafo “desconectado” Conectividad

  22. A B C E D F Ejemplo Puntos de articulación Conectividad Puntos de Articulación

  23. Árbol de expansión Definición: Un árbol T es un árbol de expansión de un grafo G si T es un subgrafo que contiene a todos los vértices de G. Conectividad

  24. Árbol de expansión • Para poder calcular los Puntos de Articulación de un grafo • Hay que obtener el árbol de expansión • Este se obtiene • A partir del Recorrido en Profundidad Ejemplo: A C D Conectividad F A B E C E B D Arco en Retroceso: Cuando se quiere visitar un nodo que ya ha sido visitado y no es el padre F

  25. Como representar el árbol de expansión • Un árbol en expansión • No es un árbol binario • Cada Vértice puede tener 0, 1 o n hijos • Si no tomamos en cuenta los arcos en retroceso, la representación depende del Grafo • Matriz de Adyacencia -> Usar un arreglo • Lista de Adyacencia -> Una lista • La representación mostrará quien es el padre de cada nodo Conectividad

  26. Árbol de expansión con matriz de adyacencia • Los vértices del grafo • Se encuentran en un arreglo • Cada índice del arreglo • Representa un vértice • Ej: A – 0, B – 1, etc. • Al representar el árbol de expansión • El padre(índice) de cada nodo puede almacenarse en un arreglo • Que también represente a los vértices A B C E Conectividad D F 0 4 0 0 5 2 1 B 0 A 2 C 3 D 4 E 5 F typedef struct TVertices{ Generico V[MAX]; int Padres[MAX]; int nvertices; }Vertices;

  27. A B C D E F Árbol de expansión con lista de adyacencia B A • Los vértices del grafo • Se encuentran en una lista • Cada nodo representa un vértice • Al representar el árbol de expansión • De cada nodo de esta lista solo nos interesa conocer al padre • Se puede añadir un dato al nodo vértice • Un enlace con el padre C E D F Conectividad typedef struct Vertice{ Generico Informacion; Vertice *padre; Lista *LArcos; }Vertice;

  28. Unión - Pertenencia En algunas aplicaciones se desea simplemente conocer si un vértice x esta o no conectado a un vértice y de un grafo, sin que sea importante el camino que los conecta. Los grafos se corresponden de forma natural con los conjuntos (colecciones de objetos): los vértices representan a los objetos y las aristas significan “esta en el mismo conjunto que”. Conectividad C {A F D E} {B C G} Conjuntos ó clases de equivalencia G B A Cada componente conexa corresponde a una clase de equivalencia diferente D E F

  29. Unión - Pertenencia El añadir una arista se corresponde con la combinación de las clases de equivalencia representadas por los vértices a conectar. El interés se centra en la pregunta fundamental “x es equivalente a y” ó “¿está x en el mismo conjunto que y?”. Esto se corresponde claramente con la pregunta fundamental de los grafos “¿está el vértice x conectado al vértice y?” Conectividad “Dado un conjunto de aristas, se puede construir una representación por lista de adyacencia que corresponda al grafo y utilizar la búsqueda en profundidad para asignar a cada vértice el índice de su correspondiente conexa y responder a las preguntas antes planteada con tal solo dos accesos a arrays y una comparación”

  30. Unión - Pertenencia Por correspondencia con el problema de los conjuntos, la adición de una nueva arista se denomina una operación de unión, y las preguntas se denominan operaciones de pertenencia. El objetivo es escribir una función que pueda verificar si dos vértices x e y pertenecen al mismo conjunto (o, en representación de grafos, a la misma componente conexa) y, en caso de que sea así, que pueda unirlos en el mismo conjunto (colocando una arista entre ellos y el grafo). En lugar de construir una lista de adyacencia directa o cualquier otra representación de los grafos, es mas eficaz utilizar una estructura interna orientada específicamente a la realización de las operaciones unión y pertenencia. Conectividad

  31. Unión - Pertenencia Esta estructura interna es un bosque de arboles, uno por cada componente conexa. Se necesita poder encontrar si dos vértices pertenecen al mismo árbol y combinar dos arboles en uno. Conectividad

  32. Unión - Pertenencia Para ilustrar como trabaja este algoritmo, vamos a ver el bosque construido por los siguientes vértices (A-B-C-D-E-F-G-H-I-J-K-L-M) cuando se le insertan estas aristas en el siguiente orden: AG - AB - AC - LM - JM - JL - JK - ED - FD - HI - FE - AF - GE - GC - GH - JG - LG. Inicialmente todos los nodos están en árboles separados (cada vértice es un árbol). Conectividad A B C D E F G H I J K L M

  33. Unión - Pertenencia Luego la arista AG crea un árbol de dos nodos con A como raíz (esta decisión es arbitraria, porque tranquilamente podríamos haber puesto G como raíz). Conectividad Las aristas AB y AC agregan B y C al árbol de la misma forma.

  34. Unión - Pertenencia Conectividad Proceso culminado

  35. Unión - Pertenencia Es necesario recalcar que, al contrario que en los árboles de búsqueda primero en profundidad, la única relación entre estos árboles de unión y el grafo original con las aristas dadas es que dividen a los vértices en grupos de la misma forma. Por ejemplo, no hay ninguna correspondencia entre los caminos que conectan nodos en los árboles y los caminos que conectan nodos en el grafo. Para representar estos árboles es apropiado usar la representación “enlace padre" porque siempre se viaja hacia arriba en los árboles, nunca hacia abajo. Específicamente, mantenemos un array padre que contiene, para cada vértice, el índice de su padre (0 si es la raíz de algún árbol), como se especifica en la próxima declaración de la clase: Conectividad

  36. Unión - Pertenencia class EQ { private: int *dad; public: EQ(int size); Int find(int x, int y, int doit); }; El constructor reserva el espacio para el array dad y setea todos sus valores inicialmente a cero (se omite el código). Se usa un solo procedimiento find para implementar ambos, la unión y la búsqueda. Si el tercer argumento es 0 se hace una búsqueda, si no es 0, se hace una unión. Para encontrar al padre del vértice j, simplemente se hace j = dad[j], y para encontrar la raíz del árbol al que pertenece j se repite esta operación hasta que se llega a 0. Conectividad

  37. Unión - Pertenencia Esto nos lleva a la siguiente implementación del procedimiento: Int EQ::find(int x, int y, int doit) { int i=x, j=y; while (dad[i] >0) i = dad[i]; while (dad[j] > 0) j=dad[j]; if (doit && (i != j)) dad[j]=i; return (i != j); } La función find retorna 0 si los dos vértices dados están en el mismo componente. Si no lo están y el flag doit esta seteado, son puestos en el mismo componente. El método es simple. Usar el array dad para llegar a la raíz del árbol que contiene cada vértice, luego chequear si las raíces son las mismas. Para mezclar el árbol con raíz j con el árbol de raíz i simplemente se setea dad[j] = i. Conectividad

  38. Unión - Pertenencia Conectividad Contenido de la estructura de datos union-pertenencia durante el proceso

  39. Unión - Pertenencia El algoritmo descrito anteriormente tiene un mal desempeño para su peor caso porque los árboles formados pueden ser degenerados. Por ejemplo, tomando en orden las aristas AB BC CD DE EF FG GH HI IJ… YZ se produce una larga cadena con Z apuntando a Y, Y apuntando a X, etc. Este tipo de estructura toma un tiempo proporcional a V2 para construirse y tiene un tiempo proporcional a V para una prueba promedio de equivalencia. Conectividad

  40. Unión - Pertenencia Varios métodos han sido sugeridos para lidiar con esta dificultad. Un método natural es tratar de hacer lo correcto para mezclar dos árboles, en lugar de hacer arbitrariamente dad[ j ] = i. Cuando un árbol con raíz en i va a ser mezclado con otro con raíz en j, uno de los nodos debe mantenerse como raíz y el otro (y todos sus descendientes) deben ir un nivel más abajo en el árbol. Para minimizar la distancia a la raíz de la mayoría de los nodos tiene sentido elegir como raíz el nodo con más descendientes. Conectividad

  41. Unión - Pertenencia Esta idea, llamada equilibrado de peso, es fácilmente implementable manteniendo el tamaño de cada árbol (cantidad de descendientes de la raíz) en el array dad para cada nodo raíz, codificado como un número no positivo de tal modo que el nodo raíz pueda ser detectado cuando se viaja hacia arriba en el árbol con find. Conectividad

  42. Unión - Pertenencia Idealmente se desearía que cada nodo apuntara directamente a la raíz de su árbol. Sin importar que estrategia se use, para lograr este objetivo se necesita examinar al menos todos los nodos en uno de los dos árboles a mezclar y esto puede ser demasiado comparado con los pocos nodos en el camino a la raíz que find generalmente examina. Sin embargo podemos aproximarnos a este ideal haciendo que todos los nodos que sí se examinan apunten a la raíz. Este método, conocido como compresión de caminos, se implementa fácilmente haciendo otra pasada por cada árbol, después de que la raíz fue encontrada, y seteando la entrada dad de cada vértice encontrado a lo largo del camino para que apunte a la raíz. Conectividad

  43. Unión - Pertenencia La combinación de compresión de caminos y equilibrado de peso nos aseguran que los algoritmos van a correr muy rápido. La siguiente implementación muestra que el código extra necesario es un pequeño precio a pagar para protegernos de los casos degenerados. int EQ::find(int x, int y, int doit) { int t, i=x, j=y; while (dad[i] > 0) i=dad[i]; while (dad[j] > 0) j=dad[j]; while (dad[x]>0) { t=x; x=dad[x]; dad[t]=i; } while (dad[y]>0) { t=y; y=dad[y]; dad[t]=j; } if (doit && (i != j)) if (dad[j] < dad[i]) { dad[j]+=dad[i] - 1; dad[i]=j; } else { dad[i]+=dad[j] - 1; dad[j]=i; } return (i !=j ); } Conectividad

  44. Unión - Pertenencia Conectividad Proceso culminado al aplicar el método, equilibrado, con compresión de caminos

  45. Unión - Pertenencia Conectividad Contenido de la estructura de datos union-pertenencia durante el proceso con el método equilibrado, con compresión de caminos

  46. Problemática Con frecuencia se desea modelar problemas prácticos utilizando grafos en los que se asocia a las aristas unos pesos o costes. En un mapa de líneas aéreas, en el que las aristas representan rutas de vuelo, los pesos pueden representar distancias o tarifas. Estas situaciones hacen aparecer de forma natural cuestiones como el minimizar costes. Grafos ponderados

  47. Problemática Se examinara los algoritmos de dos de estos problemas: • Encontrar la forma de conectar todos los puntos al menor coste (problema del árbol de expansión mínima). • Encontrar el camino de menor coste entre dos puntos dados (problema del camino mas corto). Grafos ponderados La forma de representar a los grafos ponderados es obvia. En la representación por matriz de adyacencia, la matriz puede contener pesos de aristas en lugar de valores booleanos y en la representación por listas de adyacencia se puede añadir un campo a cada elemento de la lista, a manera de peso.

  48. Árbol de expansión mínimo Un árbol de expansión mínimo de un grafo ponderado es una colección de aristas que conectan todos los vértices y en el que la suma de los pesos de las aristas es al menos inferior a la suma de los pesos de cualquier otra colección de aristas que conecten todos los vértices. Grafos ponderados - AEM

  49. Algoritmo genérico Se puede construir el árbol de expansión mínimo comenzando en cualquier vértice y tomando siempre el vértice mas próximo de todos los que se hayan elegido. En otras palabras, se busca la arista de menor peso entre todas las que conectan vértices que ya están en el árbol con vértices que no lo están todavía, y después se añade al árbol la arista y el vértice a los que conduce la anterior. Grafos ponderados - AEM