• No se han encontrado resultados

Estructuras de datos Grafos

N/A
N/A
Protected

Academic year: 2021

Share "Estructuras de datos Grafos"

Copied!
63
0
0

Texto completo

(1)

Estructuras de datos

Grafos

Dra. Elisa Schaeffer

[email protected]

PISIS / FIME / UANL

(2)

Matriz de adyacencia

(3)

Matriz de adyacencia

Un grafo G = (V, E) de n vértices etiquetados 1, 2, 3, . . . , n. Usar la matriz de adyacencia es eficiente sólo cuando G

es bastantea

denso

.

(4)

Matriz de adyacencia

Un grafo G = (V, E) de n vértices etiquetados 1, 2, 3, . . . , n. Usar la matriz de adyacencia es eficiente sólo cuando G

es bastantea

denso

. La matriz ocupa O (n2

) elementos y si m es mucho menor que n2, la mayoría del espacio reservado tiene el valor

cero.

(5)

Listas de adyacencia

Se necesita un arreglo a[], cada elemento de cuál es una lista de

largo din´amico

.

La lista de a[i] contiene las etiquetas de cada uno de los vecinos del vértice i.

El tamaño de la estructura de listas de adyacencia es

O (n + m) ≤ O (m) = O (n2

) (aunque en muchos casos es mucho menor).

Esto es muy parecido al implementar un grafo como una estructura enlazada, con punteros a todos los vecinos de cada vértice.

(6)

Búsqueda y recorrido

Recorrido = el proceso de aplicación de un método sistemático para

visitar cada v´ertice

B ´usqueda = un método sistemático para recorrer un grafo de entrada G = (V, E) con el propósito de

encontrar

un v´ertice

del G que tenga una cierta propiedad Estos algoritmos comúnmente utilizan

colas

o

pilas

.

(7)

Usos de recorridos

la búsqueda de vértices

la construcción de caminos la computación distancias la detección de ciclos

la identificación de los componentes conexos

(8)

Búsqueda en profundidad (

D

FS

)

Dado G y un vértice inicial v ∈ V

1. Crea una cola vacía L 2. Asigna u := v

3. Marca u visitado

4. Añade los vecinos

no marcados

de v al

comienzo

de L 5. Quita del comienzo de L todos los vértices marcados

6. Si L está vacía, termina

(9)

Formulación recursiva

Dado un vértice de inicio, el grafo G = (V, E) y un conjunto

L de vértices ya visitados (inicialmente L := ∅), dfs(v, G, L) { L := L ∪ {v} para todo w ∈ Γ (v) \ L : dfs(w, G, L). } Grafos– p. 7

(10)

Orden de visitas

(11)

Orden de visitas

DFS puede progresar en varias maneras.

El orden de visitas depende de cómo se elige a cuál vecino se va.

(12)

Orden de visitas

DFS puede progresar en varias maneras.

El orden de visitas depende de cómo se elige a cuál vecino se va.

Las opciones son “visitar” antes o después de llamar la subrutina para los vecinos.

(13)

Orden de visitas

DFS puede progresar en varias maneras.

El orden de visitas depende de cómo se elige a cuál vecino se va.

Las opciones son “visitar” antes o después de llamar la subrutina para los vecinos.

Si la visita se realiza

antes

de la llamada recursiva se llama el

preorden

.

(14)

Orden de visitas

DFS puede progresar en varias maneras.

El orden de visitas depende de cómo se elige a cuál vecino se va.

Las opciones son “visitar” antes o después de llamar la subrutina para los vecinos.

Si la visita se realiza

antes

de la llamada recursiva se llama el

preorden

.

(15)

Preorden y postorden

dfs(v, G, L) { L := L ∪ {v} preorden: imprimirv para todo w ∈ Γ (v) \ L : dfs(w, G, L). postorden: imprimirv } Grafos– p. 9

(16)

Complejidad asintótica

(17)

Complejidad asintótica

O (n + m)

Por arista:

procesada por máximo una vez “de ida” y otra “de vuelta”.

(18)

Complejidad asintótica

O (n + m)

Por arista:

procesada por máximo una vez “de ida” y otra “de vuelta”.

Por v´ertice:

procesado una vez; los “ya marcados” no serán revisitados.

(19)

Clasificación de las aristas

Aristas de ´arbol = las aristas por las cuales progresa el procedimiento, es decir, en la formulación recursiva,

w

fue visitado por una llamada de v

o vice versa. Estas aristas forman un

´arbol cubriente

del componente conexo del vértice de inicio.

(20)

Varios árboles posibles

Depende de la manera en que se ordena los vecinos que habrá que visitar cuáles aristan serán aristas de árbol.

v es el

padre

(directo o inmediato) de w si v lanzó la llamada recursiva para visitar a w

Si v es el padre de w, w es

hijo

v

Cada vértice, salvo que el vértice de inicio, que se llama la

ra´ız

, tiene un vértice padre único.

(21)

Antepasado y descendiente

v es un

antepasado

de w si existe una sucesión de vértices v = u1, u2, . . . , uk = w tal que ui es el padre de

ui+1.

En ese caso, w es un

descendiente

de v.

k = 2: v es el padre de w, v es el antepasado

inmediato

de w y w es un descendiente inmed. de v. La raíz es un antepasado de todos los otros vértices. Los vértices sin descendientes son

hojas

.

(22)

Otras clases de aristas

(I) Una

arista procedente

conectan un antepasado a

un descendiente

no inmediato

.

(II) Una

arista retrocedente

conecta un descendiente a

un antepasado

no inmediato

.

(III) Una

arista transversa

conecta un vértice a otro tal

que no son ni antepasados ni descendientes uno al otro — están de diferentes

ramos

del árbol.

Nota: procedentes y retrocedentes son la misma clase en un grafo no dirigido.

(23)

Nivel y altura

nivel(v) =  0, si v es la raíz,

nivel(u) + 1, si u es el padre de v.

altura(v) =  0, si v es una hoja, m´ax {altura(u) + 1} , si u es un hijo de v.

(24)

Subárbol

El subárbol de v es el árbol que es un subgrafo del árbol cubriente donde v es la raíz.

=⇒ solamente vértices que son descendientes de v están incluidos además de v mismo.

(25)

Componentes conexos

Se puede utilizar un algoritmo de recorrido para determinar los componentes conexos de un grafo.

(26)

Componentes conexos

Se puede utilizar un algoritmo de recorrido para determinar los componentes conexos de un grafo.

Un recorrido efectivamente explora

todos los caminos

que pasan por v.

(27)

Componentes conexos

Se puede utilizar un algoritmo de recorrido para determinar los componentes conexos de un grafo.

Un recorrido efectivamente explora

todos los caminos

que pasan por v.

=⇒ Por iniciar DFS en el vértice v, el conjunto de vértices

visitados por el recorrido corresponde al componente conexo de v.

(28)

Grafo no conexo

Si el grafo tiene vértices que no pertenecen al componente de v, elegimos uno de esos vértices u y corremos DFS

desde u.

=⇒ Encontramos el componente conexo que contiene a u. Iterando se determina todos los componentes conexos.

(29)

Análisis de complejidad

El número de vértices siendo n, repetimos DFS por máximo O (n) veces.

Cada recorrido toma tiempo O (n + m), pero en cada recorrido se reducen n y m.

Efectivamente vamos a visitar cada vértice una vez y recorrir cada arista una vez.

Considerando que n ∈ O (m) ∈ O (n2), tenemos un

algoritmo para identificar los componentes conexos en tiempo O (n2

).

(30)

Clasificación de aristas

En un grafo conexo, podemos clasificar las aristas según un recorrido DFS:

Asignamos al vértice inicial la etiqueta “uno”.

Siempre al visitar a un vértice por la primera vez, le asignamos una etiqueta numérica uno mayor que la última etiqueta asignada.

Los vértices llegan a tener etiquetas únicas en [1, n]. La etiqueta obtenida es

el n ´umero de inicio I

(v)

.

(31)

Más etiquetas

Asignamos otra etiqueta a cada vértice tal que la

asignación ocurre cuando todos los vecinos han sido recurridos, empezando de 1.

Así el vértice de inicio tendrá la etiqueta n.

Estas etiquetas son los

n ´umeros de final F

(v)

.

(32)

Implementaciones

Al ejecutar el algoritmo iterativo, basta con mantener las dos contadores.

Al ejecutar el algoritmo recursivo, hay que pasar los

valores de las últimas etiquetas asignadas en la llamada recursiva (iniciar con cero y cero).

(33)

Interpretación

Las I(v) definen el orden previo del recorrido.

Las F(v) definen el orden posterior del recorrido.

(34)

Clases de aristas

Una arista {v, u} (dirigida) es

una

arista de ´arbol

si el recorrido primero llegó a u

desde v,

una

arista retrocedente

si y sólo si

(I(u) > I(v)) ∧ (F (u) < F (v)),

una

arista transversa

si y sólo si

(I(u) > I(v)) ∧ (F (u) > F (v)), y

(35)

Grafo

k

-conexo

Un grafo no dirigido es k-conexo si de cada vértice hay por lo menos k caminos

distintos

a cada otro vértice.

El requisito de ser distinto puede ser de parte de

o los vértices tal que no pueden pasar por los mismos vértices ningunos de los k caminos (inglés: vertex

connectivity)

o de las aristas tal que no pueden compartir ninguna arista los caminos (inglés: edge connectivity).

(36)

Vértice de articulación

En el sentido de vértices distintos, aplica que la

intersección de dos componentes distintos que son ambos

2-conexos consiste por máximo un vértice.

(37)

Vértice de articulación

En el sentido de vértices distintos, aplica que la

intersección de dos componentes distintos que son ambos

2-conexos consiste por máximo un vértice.

Tal vértice se llama un

v´ertice de articulaci´on

.

Utilizamos esta definición para llegar a un algoritmo para

encontrar los componentes 2-conexos de un grafo no dirigido...

(38)

Componentes

2

-conexos

Sea v un vértice de articulación y tengamos un bosque de extensión del grafo.

Si v es la raíz de un árbol cubriente, tiene necesariamente por lo menos dos hijos, porque por definición de los

vértices de articulación, un recorrido no puede pasar de algún componente a otro sin pasar por v.

Si v no es la raíz, por lo menos un ramo de v contiene un componente doblemente conexo (o sea, 2-conexo). De tal ramo no es posible tener una arista retrocedente a ningún antepasado.

(39)

Distancias de la raíz

Hacemos un recorrido y marcamos para cada vértice que tan cerca de la raíz se puede llegar solamente por las

aristas de árbol y las aristas retrocedentes:

R(v) = m´ın    {I(v)} ∪    I(u) V u es un antep. de v

v o su desc. tiene arista con u       Grafos– p. 28

(40)

Vértices de articulación

Un vértice v que

no

es la raíz es un vértice de articulación si y sólo si tiene un hijo u tal que R(u) ≥ I(v).

R(v) = m´ın   

S {I(v)} ∪ {R(u) | u es un hijo de v}

{I(u) | {v, u} es una arista retrocedente}   

.

De hecho, podemos incorporar en el DFS original la

(41)

Implementación

Para facilitar la implementación, se puede guardad aristas en una pila P al procesarlos.

Cuando el algoritmo está “de vuelta” y encuentra un componente doblemente conexo, las aristas del

componente están encima de la pila y se puede quitarlas con facilidad.

(42)

Procedimiento de inicialización

inicio := 0; P := ∅; para todo v ∈ V ; I(v) := 0; para todo v ∈ V ; si I(v) = 0 doblementeconexo(v);

(43)

Procedimiento recursivo

procedimiento doblementeconexo(v)

inicio := inicio +1; I(v) := inicio; R(v) := I(v) para cada {v, u} ∈ E si I(u) = 0 añade {v, u} en P; padre(u) := v; doblementeconexo(u); si R(u) ≥ I(v)

elimina aristas de P hasta e inclusa {v, v′}; R(v) := m´ın{R(v), R(u)};

en otro caso si u 6= padre(v); R(v) := m´ın{R(v), I(u)}

(44)

Análisis

(45)

Análisis

El algoritmo visita cada vértice y recorre cada arista.

El tiempo de procesamiento de un vértice o una arista es constante, O (1).

(46)

Análisis

El algoritmo visita cada vértice y recorre cada arista.

El tiempo de procesamiento de un vértice o una arista es constante, O (1).

(47)

Fuertemente conexo

Un grafo dirigido está

fuertemente conexo

si de cada uno de sus vértices existe un camino dirigido a cada otro vértice.

Sus

componentes fuertemente conexos

son los subgrafos maximales fuertemente conexos.

(48)
(49)

Partición de vértices

Los componentes fuertemente conexos de G = (V, E)

determinan una

partici´on de los v´ertices

de G a las clases de equivalencia según la relación de clausura reflexiva y transitiva de la relación de aristas E.

Las aristas entre los componentes fuertemente conexos determinan una orden parcial en el conjunto de

componentes. Ese orden parcial se puede aumentar a un orden lineal por un algoritmo de

ordenaci´on topol´ogica

.

(50)

Ordenación topológica

Cuando uno realiza un DFS, los vértices de un componente

conexo se quedan en el mismo ramo del árbol cubriente. El vértice que queda como la raíz del ramo se dice la raíz del componente.

Meta

: encontrar las raíces de los componentes según el orden de su F(v).

(51)

Implementación

Al llegar a una raíz vi, su componente está formado por los

vértices que fueron visitados en el ramo de vi pero no

fueron clasificados a ninguna raíz anterior v1, . . . , vi−1.

Esto se puede implementar fácilmente con una pila auxiliar

P, empujando los vértices en la pila en el orden del DFS y al llegar a una raíz, quitándolos del encima de la pila hasta llegar a la raíz misma.

Así nada más el componente está eliminado de la pila.

(52)

Identificación de las raíces

Si el grafo contiene solamente aristas de árbol, cada vértice forma su propio componente.

Las aristas procedentes no tienen ningún efecto en los componentes.

Para que una vértice pueda pertenecer en el mismo componente con otro vértice, tienen que ser

conectados por un camino que contiene aristas retrocedentes o transversas.

(53)

Ejemplo de tal camino

Situaciones en las cuales dos vértices (en gris) pueden pertenecer en el mismo componente fuertemente conexo.

Las aristas azules son retrocedentes y las aristas verdes transversas. Las aristas de árbol están dibujados en negro y otros vértices (del mismo componente) en blanco.

(54)

La búsqueda de las raíces

Utilizamos un arreglo auxiliar A(v) para guadrar un número para cáda vértice encontrado:

A(v) = m´ın {{I(v)} ∪          I(v′)

∃w que es desc. de v tal que V {w, u} es retroced. o transv.

raíz del comp. de u es un antep. de v

                 

(55)

Ejemplo de la ecuación

w u

v

La raíz del componente está dibujado en gris y la flecha no continua es un camino, no necesariamente una arista directa.

(56)

Formulación recursiva

Si A(v) = I(v), sabemos que v es una raíz de un componente.

∀v ∈ V : A(v) < I(v), porque A(v) contiene el valor del

I(v) de un vértice anteriormente recorrido por una arista retrocedente o transversa o alternativamente un valor de

A(v) está pasado a v por un descendiente.

A(v) = m´ınn {I(v)}

∪ {A(u) | u es hijo de v}

(57)

Implementación

Durante la ejecución el algoritmo, en la pila auxiliar P

habrá vértices los componentes de los cuales no han sido determinados todavía.

Para facilitar el procesamiento, mantenemos un arreglo de indicadores: g(v) = verdadero si v está en la pila auxiliar

y falso en otro caso.

Así podemos determinar en el momento de procesar una arista retrocedente o transversa {v, u} si la raíz de u es un antepasado de v.

Si lo es, u está en el mismo componente con v y los dos vértices v y la raíz están todavía en la pila.

(58)

main

(

V, E

)

a := 0; I(v) := 0; P := ∅;

para todo v ∈ V haz I(v) := 0;

g(v) := falso para todo v ∈ V si I(v) = 0

(59)

fuerteconexo

(

v

)

a := a + 1; I(v) := a; A(v) := I(v); empuja v en P; g[v] := verdadero ; para todo {v, u} ∈ E haz

si I(u) = 0

fuerteconexo(u); A(v) := m´ın{A(v), A(u)}; en otro caso

si I(u) < I(v) ∧ g(u) = verdadero A(v) := m´ın{A(v), I(u)};

si A(v) = I(v)

quita de P un w hasta e incluso v; g(w) := falso ;

imprime w como miembro de compo. de v;

(60)

Análisis

Cada vértice entra la pila P una vez y sale una vez. Adicionamente hay que procesar cada arista.

La computación por vértice o arista es de tiempo constante.

=⇒

(61)

Búsqueda en anchura (

B

FS

)

1. crea una cola vacía L

2. asigna u := v

3. marca u visitado

4. añade

cada

vértice

no marcado

en Γ (v) al

fin

de L

5. si L está vacía, termina

6. asigna u := el

primer

vértice en L

7. continua de paso (3)

(62)

Usos de

B

FS

búsqueda distancias

detección de ciclos

componentes conexos

(63)

Tarea para entregar el martes

Diseña basado en BFS y expresa en pseudocódigo

algoritmos para los siguientes problemas:

1. Calcular las

distancias

del vértice v a los otros vértices en un grafo dado G.

2. Determinar si un dado grafo G es

c´ıclico

. 3. Determinar si un dado grafo G es

bipartito

. 4.

Colorear

un dado grafo G con 2 colores, si es

posible.

Referencias

Documento similar

Las lecturas de francobordo/calado se toman para establecer la posición de la flotación y determinar a su vez el desplazamiento del buque en el momento de realizar la prueba

Un método de estudio aparte de ser una herramienta muy útil al momento de estudiar también nos ayuda a agilizar nuestra mente y tener una buena memoria para futuro?. Palabras

o Si dispone en su establecimiento de alguna silla de ruedas Jazz S50 o 708D cuyo nº de serie figura en el anexo 1 de esta nota informativa, consulte la nota de aviso de la

En cada antecedente debe considerarse como mínimo: Autor, Nombre de la Investigación, año de la investigación, objetivo, metodología de la investigación,

La Tabla 5 reporta los resultados obtenidos para este experimento y se encuentra organizada de la siguiente forma: las tres primeras columnas muestran las características de

On the other hand, when contemplating limited sensing ranges, studies often focus on robots with unitary inertias, i.e., heterogeneous multi-robot systems. As the previ- ously

El quincenario de los frailes de Filipinas, condena para el Archipiélago los propósitos de nivelación jurídica que para todo territorio español, peninsular o ultramarino, se

1) Resolver la complejidad técnica de integrar información semejante pero que está representada de manera diversa. 2) Lograr la interoperabilidad entre plataformas de