OBJETIVOS ] Definiciones formales de grafo y conceptos relacionados ] Estructuras de datos para representar grafos ] Algoritmos para resolver diferentes variantes del problema de encontrar el camino mínimo sobre un grafo ] Algoritmos para resolver el problema de encontrar el árbol de extensión de coste mínimo sobre un grafo Tema 9: GRAFOS Primera Parte Estructuras de Datos y Algoritmos Curso 2002/03 Grafos. EDA. Curso 2002/03 ÍNDICE ] ] ] ] ] ] BIBLIOGRAFÍA 1. Introducción 2. Conceptos Básicos 3. Implementación de grafos 4. Recorridos de grafos 5. Búsqueda del camino con peso mínimo: algoritmo de Dijkstra 6. Otros problemas de caminos en GAD \ Ordenación topológica \ Búsqueda de caminos mínimos ] 7. Problema de obtención de árboles de extensión sobre grafos no dirigidos \ Algoritmos de Prim y Kruskal Grafos. EDA. Curso 2002/03 2 Básica: ] Weiss, M.A. Estructuras de datos en Java. Adisson-Wesley, 2000. \ Capítulos 14 y 23 Otros: ] T.H. Cormen, C.E. Leiserson, R.L. Rivest. Introduction to Algorithms. MIT Press, 1990. \ Capítulos 5 y 23. ] Aho A.V., Hopcroft J.E., Ullman J.E. Estructuras de datos y Algoritmos. Addison-Wesley, 1988. \ Capítulos 6 y 7. 3 Grafos. EDA. Curso 2002/03 4 CONCEPTOS BÁSICOS 1. INTRODUCCIÓN ] Un grafo permite representar relaciones binarias entre los elementos de un conjunto. Ejemplos: ] ] ] ] ] ] ] •Rutas de transporte •Envío de correo electrónico 25 18 35 30 21 49 Grafos dirigidos y no dirigidos Grafos etiquetados Relaciones de incidencia y adyacencia Caminos Subgrafos Conectividad Árboles y Grafos 25 23 39 Grafos. EDA. Curso 2002/03 Grafos. EDA. Curso 2002/03 5 Grafos Dirigidos (DiGrafos) Grafos no dirigidos ] Un grafo dirigido (g.d.) es un par G=(V,E) ] Un grafo no dirigido (G.N.D) es un par G=(V,E) \ V es un conjunto finito de vértices (nodos) \ E es un conjunto de arcos (o aristas). Un arco es un par ordenado(u,v) con u,v∈V 1 4 2 5 3 V={1,2,3,4,5,6} 6 E={(1,2),(2,2),(2,4),(2,5),(4,1), (4,5),(5,4),(6,3)} Grafos. EDA. Curso 2002/03 6 \ V es un conjunto finito de vértices (nodos) \ E es un conjunto de arcos (aristas). Un arco es un par NO ordenado (u,v) con u,v∈V, u≠v 1 2 3 V={1,2,3,4,5,6} E={(1,2),(1,5),(2,5),(3,6)} 4 7 5 6 Grafos. EDA. Curso 2002/03 8 Grafos Etiquetados Relaciones de Incidencia y Adyacencia ] Un grafo etiquetado es un grafo G=(V,E) sobre el que se define una función f:E->A, dónde A es un conjunto cuyas componentes se llaman etiquetas. ] Un grafo ponderado (o con pesos o costes) es un grafo etiquetado con números reales (A≡ℜ) Grafos. EDA. Curso 2002/03 Ejemplo: vértice 2 1 2 3 4 5 6 Grafos. EDA. Curso 2002/03 9 Relaciones de Incidencia y Adyacencia (cont.) 10 Relaciones de Incidencia y Adyacencia (cont.) ] Sea G=(V,E) un grafo no dirigido. Si (u,v)∈E, decimos que incide sobre u y v. ] ] Sea G=(V,E) un grafo dirigido. Si (u,v)∈E, decimos que incide desde u (sale de..) e incide en v (llega a..). Ejemplo: vértice 2 ] Sea G=(V,E) un grafo. Si (u,v)∈E, decimos que el vértice v es adyacente al u. \ La relación es simétrica en grafos no dirigidos 2 es adyacente a 1 1 NO es adyacente a 2 2 es adyacente a 1 1 es adyacente a 2 1 2 3 1 2 3 1 2 3 4 5 6 4 5 6 4 5 6 Grafos. EDA. Curso 2002/03 11 Grafos. EDA. Curso 2002/03 12 Relaciones de Incidencia y Adyacencia (cont.) ] Llamaremos grado de un vértice en un g.n.d. al nº de arcos que inciden sobre él. 1 2 3 4 5 6 13 Relaciones de Incidencia y Adyacencia (cont.) 2 3 4 5 6 1 2 3 4 5 6 Grafos. EDA. Curso 2002/03 14 Caminos ] Un camino de longitud k desde u a u’ en un grafo G=(V,E) es una secuencia de vértices 〈v0,v1,..,vk〉 tal que vo=u y vk=u’ y ∀i:1..k:(vi-1,vi)∈E. La longitud del camino es el número de arcos. ] La longitud del camino con pesos es la suma d elos costes de las aristas que forman el camino ] Si hay un camino P desde u hasta u’, decimos que u’ es alcanzable desde u via P. ] El grado de un grafo es el del vértice de máximo grado. 1 ] El grado de un vértice en un g.d. es el nº de arcos que salen de él (grado de salida) más el nº de arcos que entran (grado de entrada). Grado de entrada del 2=2, Grado de salida del 2 =3 Grado de 2=5 El grado de 2 es 2 Grafos. EDA. Curso 2002/03 Relaciones de Incidencia y Adyacencia (cont.) El grado de este grafo es 5 Grafos. EDA. Curso 2002/03 15 Grafos. EDA. Curso 2002/03 16 Caminos (cont.) Caminos (cont.) ] Un camino es simple si todos sus vértices son distintos. ] En un g.d. un camino <v0,v1,..,vk> forma un ciclo si v0=vk y el camino contiene al menos un arco. \ El ciclo es simple si los vértices son distintos \ Un bucle es un ciclo de longitud 1 1 2 3 4 5 6 1 2 3 4 5 6 <1,2,5,4> es un camino simple de longitud 3 <2,5,4,5> no es un camino simple Grafos. EDA. Curso 2002/03 <1,2,5,4> es un ciclo Grafos. EDA. Curso 2002/03 17 Caminos (cont.) 18 Ejercicio ] ] En un g.n.d. un camino <v0,v1,..,vk> forma un ciclo si v0=vk y los vi son distintos. ] Un grafo sin ciclos diremos que es acíclico (GDA) Sea G = (V,E) un Grafo dirigido con pesos V={v0,v1, v2, v3, v4, v6, v6 }, E={ (v0,v1, 2), (v0,v3, 1), (v1,v3, 3), (v1,v4, 10), (v3,v4, 2), (v3,v6, 4), (v3,v5, 8), (v3,v2, 2), (v2,v0, 4), (v2,v5, 5), (v4,v6, 6), (v6,v5, 1) } Se pide: 1.- |V| y |E| 2.- Vértices adyacentes a cada vi 3.- Grado de cada vi y del Grafo 4.- Caminos desde v0 al resto de Vértices, su longitud y su longitud con pesos 5.- Vértices alcanzables desde v0 6.- Caminos mínimos desde v0 al resto de Vértices 7.- ¿Tiene ciclos? Grafos. EDA. Curso 2002/03 19 Grafos. EDA. Curso 2002/03 20 Subgrafos Conectividad de un grafo ] Un grafo G’=(V’,E’) es un subgrafo de G=(V,E) si V’⊆V y E’⊆E. ] Dado un conjunto V’⊆V, el subgrafo de G inducido por V’ es ] Un g.n.d. es conexo si cualquier par de vértices están conectados por un camino. Las componentes conexas de un grafo son las clases de equivalencia en V definidas por la relación “es alcanzable desde..” G’=(V’,E’):E’={(u,v)∈E:u,v∈V’} Ejemplo: subgrafo inducido por {1,2,3,6} 1 2 3 4 5 6 1 2 1 2 3 4 5 6 3 6 Grafos. EDA. Curso 2002/03 Grafos. EDA. Curso 2002/03 21 22 Árboles Conectividad de un grafo (cont.) ] Un g.d. es fuertemente conexo si cualquier vértice es alcanzable desde cualquier otro. Las componentes fuertemente conexas de un grafo son las clases de equivalencia en V definidas por la relación “son mutuamente ] Un bosque es un grafo acíclico no dirigido. ] Un grafo acíclico, no dirigido y conexo es un árbol (libre). (libre) alcanzables” 1 2 3 4 5 6 (a) Árbol Grafos. EDA. Curso 2002/03 23 (b) Bosque (c) Grafo Grafos. EDA. Curso 2002/03 24 Árboles Árboles con raíz ] Un Árbol con raíz es un árbol con un vértice distinguido denominado raíz. ] Teorema: Sea G=(V,E) un g.n.d. Las siguientes afirmaciones son equivalentes: \ G es un árbol (libre) \ Cualquier par de vértices en G están conectados por un único camino simple \ G es conexo y |E|=|V|-1 \ G es acíclico pero si añadimos un arco a E, el grafo resultante contiene un ciclo 7 3 8 Dem. Pág. 91-93 [Cormen,90] 6 10 12 5 4 11 2 1 9 Grafos. EDA. Curso 2002/03 25 Árbol de recubrimiento de un gnd 4 a 11 8 h 7 8 7 c 2 i 4 g d ] Listas de Adyacencia: Adyacencia Un grafo G=(V,E) se representa como un vector de listas de vértices indexado por vértices. G[v] es una lista de los vértices emergentes y/o incidentes de/a v∈V. \ Memoria: O(|V|+|E|) \ Tiempo de acceso: O(Grado(G)) ] Matriz de Adyacencias: Adyacencias Un grafo G=(V,E) se representa como una 9 e 14 f 26 2. REPRESENTACIÓN DE GRAFOS ] Un árbol de recubrimiento del grafo G=(V,E) es un árbol libre T=(V’,E’) tal que V’=V y E’ ⊆E ] Ejemplo: b Grafos. EDA. Curso 2002/03 matriz indexada por vértices de booleanos. La componente G[u,v] es true si (u,v)∈E, sino G[u,v]=false. \ Memoria: O(|V|2) \ Tiempo de acceso: O(1) Peso total=37 10 Grafos. EDA. Curso 2002/03 27 Grafos. EDA. Curso 2002/03 28 Ejemplos Implementación de grafos ] Basada en listas de adyacencia: \ Implementación básica: [ Grafos sin pesos [ Vértices numerados desde 0 hasta |V|-1 \ Implementación de grafos ponderados [ La clase Arista \ Los vértices no están numerados desde 0 hasta |V|-1 [ Utilización de un diccionario (tabla hash) [ La clase Vertice Grafos. EDA. Curso 2002/03 Grafos. EDA. Curso 2002/03 29 Implementación básica Programa de prueba public class Grafo { private static final int TAMANYO_INICIAL=10; private Lista tabla []; private int numVertices; public Grafo() { numVertices=0; tabla=new Lista[TAMANYO_INICIAL]; } public void insArista (int orig, int dest) { if (tabla[orig]==null) tabla[orig]=new Lista(); tabla[orig].insertar(new Integer(dest)); } public String toString() { String s=""; for (int i=0; i<TAMANYO_INICIAL; i++) if (tabla[i]!=null) s+="Or:"+i+"Ady="+tabla[i].toString()+"\n"; return s; } } Grafos. EDA. Curso 2002/03 30 31 public class pruebaGrafo { public static void main (String args[]) { BufferedReader in=new BufferedReader(new InputStreamReader(System.in)); Grafo GM=new Grafo(); System.out.println("Escribe pares de vértices separados por blancos:"); try { String linea=in.readLine(); while (linea.length()!=0){ StringTokenizer st=new StringTokenizer(linea); int orig=Integer.parseInt(st.nextToken()); int dest=Integer.parseInt(st.nextToken()); GM.insArista(orig,dest); linea=in.readLine(); } }catch (IOException e) {} System.out.println("Grafo leído:"); System.out.println(GM.toString()); } } Grafos. EDA. Curso 2002/03 32 Ejemplo de ejecución Ejercicio 1 ] Definir los siguientes métodos en la clase Grafo: Escribe pares de vértices separados por blancos: 1 1 2 3 3 4 5 6 \ Método constructor para crear el grafo a partir de la información de arcos leída desde un fichero \ Método para consultar el número total de arcos de un grafo \ Método para consultar el grado de un vértice dado (grado de salida si el grafo es dirigido) \ Método para consultar el grado del grafo (grado de salida si el grafo es dirigido) \ Método para comprobar si el grafo está vacío \ Método para comprobar si un determinado arco pertenece al grafo 2 4 5 5 6 2 4 6 Grafo leído: Orig:1 Orig:2 Orig:3 Orig:4 Orig:5 Orig:6 Ady= Ady= Ady= Ady= Ady= Ady= 4 2 5 6 5 2 4 6 Grafos. EDA. Curso 2002/03 Grafos. EDA. Curso 2002/03 33 Implementación de un grafo ponderado La clase Arista public class Grafo { private static final int TAMANYO_INICIAL=10; private Lista tabla []; private int numVertices; public Grafo() { numVertices=0; tabla=new Lista[TAMANYO_INICIAL]; } public void insArista (int orig, int dest, int coste) { if (tabla[orig]==null) tabla[orig]=new Lista(); tabla[orig].insertar(new Arista(dest,coste)); } public String toString() { String s=""; for (int i=0; i<TAMANYO_INICIAL; i++) if (tabla[i]!=null) s+="Or:"+i+"Ady="+tabla[i].toString()+"\n"; return s; } } Grafos. EDA. Curso 2002/03 34 35 public class Arista { // atributos: el vértice destino y el coste del arco private int dest; private int coste; public Arista(int v, int c) { dest=v;coste=c; } public String toString(){ return dest+“ ("+coste+")"; } } Grafos. EDA. Curso 2002/03 36 Implementación de grafos en Java Los nombres de los vértices... ] En general, los vértices tendrán nombres asociados, típicamente cadenas de caracteres: ] La clase Grafo ] La clase Arista ] La clase Vértice Grafo Es un vector de... \ Se mantendrá una tabla hash con la codificación de cada vértice \ Los códigos se asignan internamente con valores entre 0 y el número de vértices menos 1, conforme se va leyendo el grafo Vértices Tiene una lista de... Grafos. EDA. Curso 2002/03 Ejemplo: D C 10 A B 12 D B 23 A D 87 E D 43 B E 11 C A 19 Aristas DICCIONARIO D 0 C 1 A 2 B 3 E 4 Grafos. EDA. Curso 2002/03 37 La implementación del diccionario 38 La clase Vertice class ElementoHash implements Hashable { public class Vertice { String nombre; //el nombre del vértice Lista ady; // la lista de vértices adyacentes (aristas) String nombre; int codigo; public ElementoHash (String nom) { nombre=nom; } public int hash () { return ExploracionTablaCuadratica.hash(nombre); } public boolean equals (Object x) { return nombre.equals( ((ElementoHash)x).nombre ); } public Vertice(String v) { nombre=v; ady=new Lista(); } public String toString() { return ady.toString(); } } } Grafos. EDA. Curso 2002/03 39 Grafos. EDA. Curso 2002/03 40 La clase Grafo El método constructor de Grafo public class Grafo { private private private private public Grafo() { numVertices=0; static final int TAMANYO_INICIAL=10; Vertice tabla []; int numVertices; TablaHash diccio; tabla=new Vertice[TAMANYO_INICIAL]; diccio=new ExploracionTablaCuadratica(); } public Grafo() { ... } public insArista (String orig,String dest,int cost) { ... } public String toString() { ... } } Grafos. EDA. Curso 2002/03 Grafos. EDA. Curso 2002/03 41 La operación insArista 42 La codificación de los vértices private int insNodo (String nomVertice) { ElementoHash aux = new ElementoHash(nomVertice); ElementoHash res; try { res= (ElementoHash) diccio.buscar(aux); return res.codigo; //Si ya está en el diccionario devolvemos su código }catch (ElementoNoEncontrado e) { public void insArista (String orig, String dest, int cost) { int codOrig=insNodo(orig); int codDest=insNodo(dest); Lista aux=tabla[codOrig].ady; aux.insertar(new Arista(codDest,cost)); } // Si no está, la añadimos al diccionario e incrementamos numVertices // Si fuera necesario se duplica la tabla de vértices aux.codigo=numVertices; diccio.insertar(aux); if (numVertices==tabla.length) duplicarvectorTabla(); tabla[numVertices]=new Vertice(aux.nombre); return numVertices++; } } Grafos. EDA. Curso 2002/03 43 Grafos. EDA. Curso 2002/03 44 Ejercicio 3: definir el método toString en Grafo de forma que se muestren siempre los Vértices mediante sus etiquetas, y no con la representación numérica interna Ejercicio 2 ] Repetir el ejercicio número 1 sobre la implementación completa de grafo (usando el diccionario) public String toString() { String elGrafo =“”; for (int i=0;i<=numVertices;i++) { elGrafo+=“Vértice: ”+tabla[i].nombre+“ con Adyacentes”; Lista adyacentesAI = tabla[i].ady; adyacentesAI.inicio(); while ( !adyacentesAI.esFin()) { Arista actual = (Arista)adyacentesAI.recupera(); int numActual = actual.dest; String nombreActual = tabla[numActual].nombre; elGrafo+=“ (”+nombreActual+“, ”+actual.coste+“), ”; } elGrafo+=“\n”; return elGrafo; Grafos. EDA. Curso 2002/03 45 } } Grafos. EDA. Curso 2002/03 46