Вы находитесь на странице: 1из 111

Algoritmos em Grafos

ltima alterao: 10 de Outubro de 2006

elaboradas por Charles Ornelas, Leonardo Rocha, Leonardo Mata e Nivio Ziviani

Transparncias

Projeto de Algoritmos Cap.7 Algoritmos em Grafos

Motivao
Muitas aplicaes em computao necessitam considerar conjunto de conexes entre pares de objetos: Existe um caminho para ir de um objeto a outro seguindo as conexes? Qual a menor distncia entre um objeto e outro objeto? Quantos outros objetos podem ser alcanados a partir de um determinado objeto? Existe um tipo abstrato chamado grafo que usado para modelar tais situaes.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos

Aplicaes
Alguns exemplos de problemas prticos que podem ser resolvidos atravs de uma modelagem em grafos: Ajudar mquinas de busca a localizar informao relevante na Web. Descobrir os melhores casamentos entre posies disponveis em empresas e pessoas que aplicaram para as posies de interesse. Descobrir qual o roteiro mais curto para visitar as principais cidades de uma regio turstica.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.1

Conceitos Bsicos
Grafo: conjunto de vrtices e arestas. Vrtice: objeto simples que pode ter nome e outros atributos. Aresta: conexo entre dois vrtices.
3

aresta
1 4

vrtice

Notao: G = (V, A) G: grafo V: conjunto de vrtices A: conjunto de arestas

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.1

Grafos Direcionados
Um grafo direcionado G um par (V, A), onde V um conjunto nito de vrtices e A uma relao binria em V . Uma aresta (u, v ) sai do vrtice u e entra no vrtice v . O vrtice v adjacente ao vrtice u. Podem existir arestas de um vrtice para ele mesmo, chamadas de self-loops.
0 1 4

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.1

Grafos No Direcionados
Um grafo no direcionado G um par (V, A), onde o conjunto de arestas A constitudo de pares de vrtices no ordenados. As arestas (u, v ) e (v, u) so consideradas como uma nica aresta. A relao de adjacncia simtrica. Self-loops no so permitidos.
0 1 4

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.1

Grau de um Vrtice
Em grafos no direcionados: O grau de um vrtice o nmero de arestas que incidem nele. Um vrice de grau zero dito isolado ou no conectado. Ex.: O vrtice 1 tem grau 2 e o vrtice 3 isolado.
0 1 4

Em grafos direcionados O grau de um vrtice o nmero de arestas que saem dele (out-degree) mais o nmero de arestas que chegam nele (in-degree). Ex.: O vrtice 2 tem in-degree 2, out-degree 2 e grau 4.
0 1 4

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.1

Caminho entre Vrtices


Um caminho de comprimento k de um vrtice x a um vrtice y em um grafo G = (V, A) uma seqncia de vrtices (v0 , v1 , v2 , . . . , vk ) tal que x = v0 e y = vk , e (vi1 , vi ) A para i = 1, 2, . . . , k . O comprimento de um caminho o nmero de arestas nele, isto , o caminho contm os vrtices v0 , v1 , v2 , . . . , vk e as arestas (v0 , v1 ), (v1 , v2 ), . . . , (vk1 , vk ). Se existir um caminho c de x a y ento y alcanvel a partir de x via c. Um caminho simples se todos os vrtices do caminho so distintos. Ex.: O caminho (0, 1, 2, 3) simples e tem comprimento 3. O caminho (1, 3, 0, 3) no simples.
0 1 4

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.1

Ciclos
Em um grafo direcionado: Um caminho (v0 , v1 , . . . , vk ) forma um ciclo se v0 = vk e o caminho contm pelo menos uma aresta. O ciclo simples se os vrtices v1 , v2 , . . . , vk so distintos. O self-loop um ciclo de tamanho 1. Dois caminhos (v0 , v1 , . . . , vk ) e (v0 , v1 , . . . , vk ) formam o mesmo ciclo se existir um inteiro j tal que vi = v(i+j ) mod k para i = 0, 1, . . . , k 1. Ex.: O caminho (0, 1, 2, 3, 0) forma um ciclo. O caminho(0, 1, 3, 0) forma o mesmo ciclo que os caminhos (1, 3, 0, 1) e (3, 0, 1, 3).
0 1 4

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.1

Ciclos
Em um grafo no direcionado: Um caminho (v0 , v1 , . . . , vk ) forma um ciclo se v0 = vk e o caminho contm pelo menos trs arestas. O ciclo simples se os vrtices v1 , v2 , . . . , vk so distintos. Ex.: O caminho (0, 1, 2, 0) um ciclo.
0 1 4

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.1

10

Componentes Conectados
Um grafo no direcionado conectado se cada par de vrtices est conectado por um caminho. Os componentes conectados so as pores conectadas de um grafo. Um grafo no direcionado conectado se ele tem exatamente um componente conectado. Ex.: Os componentes so: {0, 1, 2}, {4, 5} e {3}.
0 1 4

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.1

11

Componentes Fortemente Conectados


Um grafo direcionado G = (V, A) fortemente conectado se cada dois vrtices quaisquer so alcanveis a partir um do outro. Os componentes fortemente conectados de um grafo direcionado so conjuntos de vrtices sob a relao so mutuamente alcanveis. Um grafo direcionado fortemente conectado tem apenas um componente fortemente conectado. Ex.: {0, 1, 2, 3}, {4} e {5} so os componentes fortemente conectados, {4, 5} no o pois o vrtice 5 no alcanvel a partir do vrtice 4.
0 1 4

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.1

12

Grafos Isomorfos
G = (V, A) e G = (V , A ) so isomorfos se existir uma bijeo f : V V tal que (u, v ) A se e somente se (f (u), f (v )) A .
0 4 5 1

7 3

6 2

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.1

13

Subgrafos
Um grafo G = (V , A ) um subgrafo de G = (V, A) se V V e A A. Dado um conjunto V V , o subgrafo induzido por V o grafo G = (V , A ), onde A = {(u, v ) A|u, v V }. Ex.: Subgrafo induzido pelo conjunto de vrtices {1, 2, 4, 5}.
0 1 4

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.1

14

Verso Direcionada de um Grafo No Direcionado


A verso direcionada de um grafo no direcionado G = (V, A) um grafo direcionado G = (V , A ) onde (u, v ) A se e somente se (u, v ) A. Cada aresta no direcionada (u, v ) em G substituda por duas arestas direcionadas (u, v ) e (v, u) Em um grafo direcionado, um vizinho de um vrtice u qualquer vrtice adjacente a u na verso no direcionada de G.
0 1 0 1

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.1

15

Verso No Direcionada de um Grafo Direcionado


A verso no direcionada de um grafo direcionado G = (V, A) um grafo no direcionado G = (V , A ) onde (u, v ) A se e somente se u = v e (u, v ) A. A verso no direcionada contm as arestas de G sem a direo e sem os self-loops. Em um grafo no direcionado, u e v so vizinhos se eles so adjacentes.
0 1 4 0 1 4

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.1

16

Outras Classicaes de Grafos


Grafo ponderado: possui pesos associados s arestas. Grafo bipartido: grafo no direcionado G = (V, A) no qual V pode ser particionado em dois conjuntos V1 e V2 tal que (u, v ) A implica que u V1 e v V2 ou u V2 e v V1 (todas as arestas ligam os dois conjuntos V1 e V2 ). Hipergrafo: grafo no direcionado em que cada aresta conecta um nmero arbitrrio de vrtices.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.1

17

Grafos Completos
Um grafo completo um grafo no direcionado no qual todos os pares de vrtices so adjacentes. Possui (|V |2 |V |)/2 = |V |(|V | 1)/2 arestas, pois do total de |V |2 pares possveis de vrtices devemos subtrair |V | self-loops e dividir por 2 (cada aresta ligando dois vrtices contada duas vezes). O nmero total de grafos diferentes com |V | vrtices 2|V |(|V |1)/2 (nmero de maneiras diferentes de escolher um subconjunto a partir de |V |(|V | 1)/2 possveis arestas).

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.1

18

rvores
rvore livre: grafo no direcionado acclico e conectado. comum dizer apenas que o grafo uma rvore omitindo o livre. Floresta: grafo no direcionado acclico, podendo ou no ser conectado. rvore geradora de um grafo conectado G = (V, A): subgrafo que contm todos os vrtices de G e forma uma rvore. Floresta geradora de um grafo G = (V, A): subgrafo que contm todos os vrtices de G e forma uma oresta.

(a)

(b)

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2

19

O Tipo Abstratos de Dados Grafo


Importante considerar os algoritmos em grafos como tipos abstratos de dados. Conjunto de operaes associado a uma estrutura de dados. Independncia de implementao para as operaes.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2

20

Operadores do TAD Grafo


1. Criar um grafo vazio. 2. Inserir uma aresta no grafo. 3. Vericar se existe determinada aresta no grafo. 4. Obter a lista de vrtices adjacentes a determinado vrtice. 5. Retirar uma aresta do grafo. 6. Imprimir um grafo. 7. Obter o nmero de vrtices do grafo. 8. Obter o transposto de um grafo direcionado. 9. Obter a aresta de menor peso de um grafo.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2

21

Operao Obter Lista de Adjacentes


1. Vericar se a lista de adjacentes de um vrtice v est vazia. Retorna true se a lista de adjacentes de v est vazia. 2. Obter o primeiro vrtice adjacente a um vrtice v , caso exista. Retorna o endereo do primeiro vrtice na lista de adjacentes de v . 3. Obter o prximo vrtice adjacente a um vrtice v , caso exista. Retorna a prxima aresta que o vrtice v participa.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2

22

Implementao da Operao Obter Lista de Adjacentes


comum encontrar um pseudo comando do tipo: for u iista de adjacentes (v) do { faz algo com u } O trecho de programa abaixo apresenta um possvel renamento do pseudo comando acima.
i f ( ! grafo . listaAdjVazia ( v ) ) { Aresta aux = grafo . primeiroListaAdj ( v ) ; while (aux ! = null ) { int u = aux. vertice2 ( ) ; int peso = aux.peso ( ) ; aux = grafo . proxAdj ( v ) ; } }

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.1

23

Matriz de Adjacncia
A matriz de adjacncia de um grafo G = (V, A) contendo n vrtices uma matriz n n de bits, onde A[i, j ] 1 (ou verdadeiro) se e somente se existe um arco do vrtice i para o vrtice j . Para grafos ponderados A[i, j ] contm o rtulo ou peso associado com a aresta e, neste caso, a matriz no de bits. Se no existir uma aresta de i para j ento necessrio utilizar um valor que no possa ser usado como rtulo ou peso.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.1

24

Matriz de Adjacncia - Exemplo


0 1 4 0 1 4

0 1 2 3 4 5 0 1 1 1 1 1 2 1 1 3 1 4 5

0 1 2 3 4 5 0 1 1 1 1 1 2 1 1 3 4 5

(a)

(b)

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.1

25

Matriz de Adjacncia - Anlise


Deve ser utilizada para grafos densos, onde |A| prximo de |V |2 . O tempo necessrio para acessar um elemento independente de |V | ou |A|. muito til para algoritmos em que necessitamos saber com rapidez se existe uma aresta ligando dois vrtices. A maior desvantagem que a matriz necessita (|V |2 ) de espao. Ler ou examinar a matriz tem complexidade de tempo O(|V |2 ).

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.1

26

Matriz de Adjacncia - Implementao


A insero de um novo vrtice ou retirada de um vrtice j existente pode ser realizada com custo constante.
package cap7. matrizadj ; public class Grafo { public static class Aresta { private int v1 , v2 , peso; public Aresta ( int v1 , int v2 , int peso) { this .v1 = v1 ; this .v2 = v2 ; this .peso = peso ; } public int peso ( ) { return this .peso ; } public int v1 ( ) { return this .v1 ; } public int v2 ( ) { return this .v2 ; } } private int mat [ ] [ ] ; / / pesos do tipo inteiro private int numVertices; private int pos [ ] ; / / posio atual ao se percorrer os adjs de um vrtice v public Grafo ( int numVertices ) { this .mat = new int [numVertices ] [ numVertices ] ; this .pos = new int [numVertices ] ; this .numVertices = numVertices; for ( int i = 0; i < this .numVertices ; i ++) { for ( int j = 0; j < this .numVertices ; j ++) this .mat[ i ] [ j ] = 0; this .pos[ i ] = 1; } } public void insereAresta ( int v1 , int v2 , int peso) { this .mat[v1 ] [ v2] = peso ; } public boolean existeAresta ( int v1 , int v2 ) { return ( this .mat[v1 ] [ v2] > 0); }

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.1

27

Matriz de Adjacncia - Implementao


public boolean listaAdjVazia ( int v ) { for ( int i =0; i < this .numVertices ; i ++) i f ( this .mat[ v ] [ i ] > 0) return false ; return true ; } public Aresta primeiroListaAdj ( int v ) { / / Retorna a primeira aresta que o vrtice v participa ou / / null se a lista de adjacncia de v for vazia this .pos[ v] = 1; return this . proxAdj ( v ) ; } public Aresta proxAdj ( int v ) { / / Retorna a prxima aresta que o vrtice v participa ou / / null se a lista de adjacncia de v estiver no m this .pos[ v] ++; while ( ( this .pos[ v] < this .numVertices) && ( this .mat[ v ] [ this .pos[ v] ] = = 0 ) ) this .pos[ v]++; i f ( this .pos[ v] == this .numVertices ) return null ; else return new Aresta ( v , this .pos[ v ] , this .mat[ v ] [ this .pos[ v ] ] ) ; } public Aresta retiraAresta ( int v1 , int v2 ) { i f ( this .mat[v1 ] [ v2] == 0) return null ; / / Aresta no existe else { Aresta aresta = new Aresta ( v1 , v2 , this .mat[v1 ] [ v2 ] ) ; this .mat[v1 ] [ v2] = 0 ; return aresta ; } }

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.1

28

Matriz de Adjacncia - Implementao


public void imprime ( ) { System. out . print ( " " ); " ); for ( int i = 0; i < this .numVertices ; i ++) System. out . print ( i + " System. out . println ( ) ; for ( int i = 0; i < this .numVertices ; i ++) { System. out . print ( i + " " ); " ); for ( int j = 0; j < this .numVertices ; j ++) System. out . print ( this .mat[ i ] [ j ] + " System. out . println ( ) ; } } public int numVertices ( ) { return this .numVertices; } }

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.2

29

Listas de Adjacncia usando Estruturas Auto-Referenciadas


3 5 0 1 7 3 2 1 2 3 0 1 7 3 2 1 2 3 1 5 0 5 1 7 2 7 1 5 1 3 2 7

5 0

Um arranjo adj de |V | listas, uma para cada vrtice em V . Para cada u V , adj [u] contm todos os vrtices adjacentes a u em G.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.2

30

Listas de adjacncia - Anlise


Os vrtices de uma lista de adjacncia so em geral armazenados em uma ordem arbitrria. Possui uma complexidade de espao O(|V | + |A|) Indicada para grafos esparsos, onde |A| muito menor do que |V |2 . compacta e usualmente utilizada na maioria das aplicaes. A principal desvantagem que ela pode ter tempo O(|V |) para determinar se existe uma aresta entre o vrtice i e o vrtice j , pois podem existir O(|V |) vrtices na lista de adjacentes do vrtice i.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.2

31

Listas de Adjacncia usando Estruturas Auto-Referenciadas Implementao


A seguir apresentamos a implementao do tipo abstrato de dados grafo utilizando listas encadeadas implementadas por meio de estruturas auto-referenciadas para as sete primeiras operaes denidas anteriormente. A classe Aresta representa as informaes de uma aresta para que os usurios da classe Grafo possam acess-las. A classe Celula utilizada para representar uma entrada na lista de adjacncia de um vrtice do grafo. O mtodo equals usado para vericar se um vrtice qualquer v adjacente a um outro vrtice u ao se percorrer a lista de adjacentes de u.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.2

32

Listas de Adjacncia usando Estruturas Auto-Referenciadas Implementao


package cap7. listaadj . autoreferencia ; import cap3. autoreferencia . Lista ; public class Grafo { public static class Aresta { private int v1 , v2 , peso; public Aresta ( int v1 , int v2 , int peso) { this .v1 = v1 ; this .v2 = v2 ; this .peso = peso; } public int peso ( ) { return this .peso ; } public int v1 ( ) { return this .v1 ; } public int v2 ( ) { return this .v2 ; } } private static class Celula { int vertice , peso; public Celula ( int v , int p) { this . vertice = v ; this .peso = p; } public boolean equals ( Object obj ) { Celula item = ( Celula ) obj ; return ( this . vertice == item . vertice ) ; } } private Lista adj [ ] ; private int numVertices; public Grafo ( int numVertices ) { this . adj = new Lista [numVertices ] ; this .numVertices = numVertices; for ( int i = 0; i < this .numVertices ; i ++) this . adj [ i ] = new Lista ( ) ; } public void insereAresta ( int v1 , int v2 , int peso) { Celula item = new Celula ( v2 , peso) ; this . adj [v1 ] . insere ( item ) ; }

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.2

33

Listas de Adjacncia usando Estruturas Auto-Referenciadas Implementao


public boolean existeAresta ( int v1 , int v2 ) { Celula item = new Celula ( v2, 0 ) ; return ( this . adj [v1 ] . pesquisa ( item ) ! = null ) ; } public boolean listaAdjVazia ( int v ) { return this . adj [ v ] . vazia ( ) ; } public Aresta primeiroListaAdj ( int v ) { / / Retorna a primeira aresta que o vrtice v participa ou / / null se a lista de adjacncia de v for vazia Celula item = ( Celula ) this . adj [ v ] . primeiro ( ) ; return item ! = null ? new Aresta ( v , item . vertice , item .peso ) : null ; } public Aresta proxAdj ( int v ) { / / Retorna a prxima aresta que o vrtice v participa ou / / null se a lista de adjacncia de v estiver no m Celula item = ( Celula ) this . adj [ v ] . proximo ( ) ; return item ! = null ? new Aresta ( v , item . vertice , item .peso ) : null ; } public Aresta retiraAresta ( int v1 , int v2) throws Exception { Celula chave = new Celula ( v2, 0 ) ; Celula item = ( Celula ) this . adj [v1 ] . retira (chave) ; return item ! = null ? new Aresta ( v1 , v2 , item .peso ) : null ; }

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.2

34

Listas de Adjacncia usando Estruturas Auto-Referenciadas Implementao


public void imprime ( ) { for ( int i = 0; i < this .numVertices ; i ++) { System. out . println ( " Vertice " + i + " : " ) ; Celula item = ( Celula ) this . adj [ i ] . primeiro ( ) ; while ( item ! = null ) { System. out . println ( " } } } public int numVertices ( ) { return this .numVertices; } } " + item . vertice + " ( " +item .peso+ " ) " ) ; item = ( Celula ) this . adj [ i ] . proximo ( ) ;

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.3

35

Listas de Adjacncia usando Arranjos


3 0 5 1 7 3 2 A V

cab
0 1 2 3 4 5 6 4 6 2 3 1 1 2

prox peso
4 5 0 0 0 6 0

(a)

5 3 7

cab
5 0 1 7 3 2 A V 0 1 2 3 4 5 6 7 4 6 7 3 1 0 2 1

prox peso
4 5 7 0 0 6 0 0

(b)

5 5 7 7

cab: endereos do ltimo item da lista de adjacentes de cada vrtice (nas |V | primeiras posies) e os vrtices propriamente ditos (nas |A| ltimas posies) prox: endereo do prximo item da lista de adjacentes. peso: valor do peso de cada aresta do grafo (nas ltimas |A| posies).

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.3

36

Listas de Adjacncia usando Arranjos - Implementao


package cap7. listaadj . arranjo ; public class Grafo { public static class Aresta { private int v1 , v2 , peso; public Aresta ( int v1 , int v2 , int peso) { this .v1 = v1 ; this .v2 = v2 ; this .peso = peso; } public int peso ( ) { return this .peso ; } public int v1 ( ) { return this .v1 ; } public int v2 ( ) { return this .v2 ; } } private int cab [ ] , prox [ ] , peso [ ] ; private int pos [ ] ; / / posio atual ao se percorrer os adjs de um vrtice v private int numVertices , proxDisponivel ; public Grafo ( int numVertices , int numArestas) { int tam = numVertices + 2 numArestas; this .cab = new int [tam ] ; this . prox = new int [tam] ; this .peso = new int [tam ] ; this .numVertices = numVertices; this .pos = new int [ this .numVertices ] ; for ( int i = 0; i < this .numVertices ; i ++) { this . prox [ i ] = 0; this .cab[ i ] = i ; this .peso[ i ] = 0; this .pos[ i ] = i ; } this . proxDisponivel = this .numVertices; }

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.3

37

Listas de Adjacncia usando Arranjos - Implementao


public void insereAresta ( int v1 , int v2 , int peso) { i f ( this . proxDisponivel == this .cab. length ) System. out . println ( "Nao ha espaco disponivel para a aresta" ) ; else { int ind = this . proxDisponivel++; this . prox [ this .cab[v1 ] ] = ind ; this .cab[ ind ] = v2 ; this .cab[v1] = ind ; this . prox [ ind ] = 0 ; this .peso[ ind ] = peso; } } public boolean existeAresta ( int v1 , int v2 ) { for ( int i = this . prox [v1 ] ; i ! = 0 ; i = this . prox [ i ] ) i f ( this .cab[ i ] == v2) return true ; return false ; } public boolean listaAdjVazia ( int v ) { return ( this . prox [ v] == 0); } public Aresta primeiroListaAdj ( int v ) { / / Retorna a primeira aresta que o vrtice v participa ou / / null se a lista de adjacncia de v for vazia this .pos[ v ] = v ; return this . proxAdj ( v ) ; } public Aresta proxAdj ( int v ) { / / Retorna a prxima aresta que o vrtice v participa ou / / null se a lista de adjacncia de v estiver no m this .pos[ v ] = this . prox [ this .pos[ v ] ] ; i f ( this .pos[ v] == 0) return null ; else return new Aresta ( v, this .cab[pos[ v ] ] , this .peso[pos[ v ] ] ) ; }

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.3

38

Listas de Adjacncia usando Arranjos - Implementao


public Aresta retiraAresta ( int v1 , int v2 ) { int i ; for ( i = v1 ; this . prox [ i ] ! = 0 ; i = this . prox [ i ] ) i f ( this .cab[ this . prox [ i ]] == v2) break ; int ind = this . prox [ i ] ; i f ( this .cab[ ind ] == v2 ) { / / encontrou aresta Aresta aresta = new Aresta(v1 , v2 , this .peso[ ind ] ) ; this .cab[ ind ] = this .cab. length ; / / marca como removido i f ( this . prox [ ind ] == 0) this .cab[v1] = i ; / / ltimo vrtice this . prox [ i ] = this . prox [ ind ] ; return aresta ; } else return null ; } public void imprime ( ) { for ( int i = 0; i < this .numVertices ; i ++) { System. out . println ( " Vertice " + i + " : " ) ; for ( int j = this . prox [ i ] ; j ! = 0 ; j = this . prox [ j ] ) System. out . println ( " } } public int numVertices ( ) { return this .numVertices ; } } " + this .cab[ j ]+ " ( " + this .peso[ j ]+ " ) " ) ;

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.3

39

Busca em Profundidade
A busca em profundidade, do ingls depth-rst search), um algoritmo para caminhar no grafo. A estratgia buscar o mais profundo no grafo sempre que possvel. As arestas so exploradas a partir do vrtice v mais recentemente descoberto que ainda possui arestas no exploradas saindo dele. Quando todas as arestas adjacentes a v tiverem sido exploradas a busca anda para trs para explorar vrtices que saem do vrtice do qual v foi descoberto. O algoritmo a base para muitos outros algoritmos importantes, tais como vericao de grafos acclicos, ordenao topolgica e componentes fortemente conectados.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.3

40

Busca em Profundidade
Para acompanhar o progresso do algoritmo cada vrtice colorido de branco, cinza ou preto. Todos os vrtices so inicializados branco. Quando um vrtice descoberto pela primeira vez ele torna-se cinza, e tornado preto quando sua lista de adjacentes tenha sido completamente examinada. d[v ]: tempo de descoberta t[v ]: tempo de trmino do exame da lista de adjacentes de v . Estes registros so inteiros entre 1 e 2|V | pois existe um evento de descoberta e um evento de trmino para cada um dos |V | vrtices.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.3

41

Busca em Profundidade Implementao


package cap7; import cap7. listaadj . autoreferencia .Grafo; public class BuscaEmProfundidade { public static final byte branco = 0; public static byte cinza public static byte preto private Grafo grafo ; public BuscaEmProfundidade ( Grafo grafo ) { this . grafo = grafo ; int n = this . grafo .numVertices ( ) ; d = new int [n ] ; t = new int [n ] ; antecessor = new int [n ] ; } private int visitaDfs ( int u, int tempo, int cor [ ] ) { cor [u] = cinza ; this .d[u] = ++tempo; i f ( ! this . grafo . listaAdjVazia (u ) ) { Grafo. Aresta a = this . grafo . primeiroListaAdj (u) ; while (a ! = null ) { int v = a.v2 ( ) ; i f ( cor [ v] == branco ) { this . antecessor [ v ] = u; tempo = this . visitaDfs ( v , tempo, cor ) ; } a = this . grafo . proxAdj (u) ; } } cor [u] = preto ; this . t [u] = ++tempo; return tempo; } = 1; = 2;

private int d [ ] , t [ ] , antecessor [ ] ;

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.3

42

Busca em Profundidade Implementao


public void buscaEmProfundidade ( ) { int tempo = 0; int cor [ ] = new int [ this . grafo .numVertices ( ) ] ; for ( int u = 0; u < grafo .numVertices ( ) ; u++) { cor [u] = branco ; this . antecessor [u] = 1; } for ( int u = 0; u < grafo .numVertices ( ) ; u++) i f ( cor [u] == branco ) tempo = this . visitaDfs ( u, tempo, cor ) ; } public int d ( int v ) { return this .d[ v ] ; } public int t ( int v ) { return this . t [ v ] ; } public int antecessor ( int v ) { return this . antecessor [ v ] ; } }

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.3

43

Busca em Profundidade - Exemplo


b( / ) 0 b( / ) 1 b( / ) b( / ) 2 3 b( / ) 2 c(1/ ) 0 b( / ) 1 b( / ) 3

(a)
c(1/ ) 0 c(2/ ) 1 b( / ) b( / ) 2 3 c(1/ ) 0

(b)
c(2/ ) 1 b( / ) c(3/ ) 2 3

(c)
c(1/ ) 0 c(2/ ) 1

(d)

b( / ) p(3/4) 2 3

(e)

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.3

44

Busca em Profundidade - Exemplo


c(1/ ) 0 p(2/5) 1 b( / ) p(3/4) 2 3 p(3/4) 2 p(1/6) 0 p(2/5) 1 b( / ) 3

(f)
p(1/6) 0 p(2/5) 1 c(7/ ) p(3/4) 2 3 p(1/6) 0

(g)
p(2/5) 1 p(7/8) p(3/4) 2 3

(h)

(i)

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.3

45

Busca em Profundidade - Anlise


Os dois anis do mtodo buscaEmProfundidade tm custo O(|V |) cada um, a menos da chamada do mtodo visitaDfs (u, tempo , cor ) no segundo anel. O mtodo visitaDfs chamado exatamente uma vez para cada vrtice u V , desde que visitaDfs seja chamado apenas para vrtices brancos, e a primeira ao pintar o vrtice de cinza. Durante a execuo de visitaDfs (u, tempo , cor ), o anel principal executado |adj [u]| vezes. Desde que |adj [u]| = O(|A|),
uV

o tempo total de execuo de visitaDfs O(|A|). Logo, a complexidade total do mtodo buscaEmProfundidade O(|V | + |A|).

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.3.1

46

Classicao de Arestas
Existem: 1. Arestas de rvore: so arestas de uma rvore de busca em profundidade. A aresta (u, v ) uma aresta de rvore se v foi descoberto pela primeira vez ao percorrer a aresta (u, v ). 2. Arestas de retorno: conectam um vrtice u com um antecessor v em uma rvore de busca em profundidade (inclui self-loops). 3. Arestas de avano: no pertencem rvore de busca em profundidade mas conectam um vrtice a um descendente que pertence rvore de busca em profundidade. 4. Arestas de cruzamento: podem conectar vrtices na mesma rvore de busca em profundidade, ou em duas rvores diferentes.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.3.1

47

Classicao de Arestas
Classicao de arestas pode ser til para derivar outros algoritmos. Na busca em profundidade cada aresta pode ser classicada pela cor do vrtice que alcanado pela primeira vez: Branco indica uma aresta de rvore. Cinza indica uma aresta de retorno. Preto indica uma aresta de avano quando u descoberto antes de v ou uma aresta de cruzamento caso contrrio.
3/6 2 arv 3 4/5 arv ret cruz 4 7/8 2/9 1 arv avan cruz 5 11/12 cruz arv 1/10 0

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.3.2

48

Teste para Vericar se Grafo Acclico


A busca em profundidade pode ser usada para vericar se um grafo acclico ou contm um ou mais ciclos. Se uma aresta de retorno encontrada durante a busca em profundidade em G, ento o grafo tem ciclo. Um grafo direcionado G acclico se e somente se a busca em profundidade em G no apresentar arestas de retorno.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.4

49

Busca em Largura
Expande a fronteira entre vrtices descobertos e no descobertos uniformemente atravs da largura da fronteira. O algoritmo descobre todos os vrtices a uma distncia k do vrtice origem antes de descobrir qualquer vrtice a uma distncia k + 1. O grafo G(V, A) pode ser direcionado ou no direcionado.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.4

50

Busca em Largura
Cada vrtice colorido de branco, cinza ou preto. Todos os vrtices so inicializados branco. Quando um vrtice descoberto pela primeira vez ele torna-se cinza. Vrtices cinza e preto j foram descobertos, mas so distinguidos para assegurar que a busca ocorra em largura. Se (u, v ) A e o vrtice u preto, ento o vrtice v tem que ser cinza ou preto. Vrtices cinza podem ter alguns vrtices adjacentes brancos, e eles representam a fronteira entre vrtices descobertos e no descobertos.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.4

51

Busca em Largura - Implementao


package cap7; import cap3. autoreferencia . Fila ; import cap7. listaadj . autoreferencia .Grafo; public class BuscaEmLargura { public static final byte branco = 0; public static byte cinza public static byte preto private int d [ ] , antecessor [ ] ; private Grafo grafo ; public BuscaEmLargura ( Grafo grafo ) { this . grafo = grafo ; int n = this . grafo .numVertices ( ) ; this .d = new int [n ] ; this . antecessor = new int [n ] ; } private void visitaBfs ( int u, int cor [ ] ) throws Exception { cor [u] = cinza ; this .d[u] = 0; Fila f i l a = new Fila ( ) ; f i l a . enfileira (new Integer (u) ) ; while ( ! f i l a . vazia ( ) ) { Integer aux = ( Integer ) f i l a . desenfileira ( ) ; u = aux. intValue ( ) ; i f ( ! this . grafo . listaAdjVazia (u ) ) { Grafo. Aresta a = this . grafo . primeiroListaAdj (u) ; while (a ! = null ) { int v = a.v2 ( ) ; i f ( cor [ v] == branco ) { cor [ v ] = cinza ; this .d[ v ] = this .d[u] + 1; this . antecessor [ v ] = u ; f i l a . enfileira (new Integer ( v ) ) ; } a = this . grafo . proxAdj (u) ; } } cor [u] = preto ; } } = 1; = 2;

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.4

52

Busca em Largura - Implementao


public void buscaEmLargura ( ) throws Exception { int cor [ ] = new int [ this . grafo .numVertices ( ) ] ; for ( int u = 0; u < grafo .numVertices ( ) ; u++) { cor [u] = branco ; this .d[u] = Integer . MAX_VALUE ; this . antecessor [u] = 1; } for ( int u = 0; u < grafo .numVertices ( ) ; u++) i f ( cor [u] == branco ) this . visitaBfs ( u, cor ) ; } public int d ( int v ) { return this .d[ v ] ; } public int antecessor ( int v ) { return this . antecessor [ v ] ; } }

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.4

53

Busca em Largura - Exemplo


(a)
c(0) 0 b( ) 1 b( ) 4 p(0) 0

(b)
c(1) 1 b( ) 4

3 b( )

2 b( ) F 0 0

5 b( )

3 c(1)

2 b( ) F 1 3 1 1

5 b( )

(c)
p(0) 0 p(1) 1 b( ) 4 p(0) 0

(d)
p(1) 1 b( ) 4

3 c(1)

2 c(2) F 3 2 1 2

5 b( )

3 p(1)

2 c(2) F 2 2

5 b( )

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.4

54

Busca em Largura - Exemplo


(e)
p(0) 0 p(1) 1 b( ) 4 p(0) 0

(f)
p(1) 1 c(0) 4

3 p(1)

2 p(2) F

5 b( )

3 p(1)

2 p(2) F 4 0

5 b( )

(g)
p(0) 0 p(1) 1 p(0) 4 p(0) 0

(h)
p(1) 1 p(0) 4

3 p(1)

2 p(2) F 5 1

5 c(1)

3 p(1)

2 p(2) F

5 p(1)

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.4

55

Busca em Largura - Anlise (para listas de adjacncia)


O custo de inicializao do primeiro anel no mtodo buscaEmLargura O(|V |). O custo do segundo anel tambm O(|V |). Mtodo visitaBfs : enleirar e desenleirar tm custo O(1), logo, o custo total com a la O(|V |). Cada lista de adjacentes percorrida no mximo uma vez, quando o vrtice desenleirado. Desde que a soma de todas as listas de adjacentes O(|A|), o tempo total gasto com as listas de adjacentes O(|A|). Complexidade total: O(|V | + |A|).

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.4

56

Caminhos Mais Curtos


A busca em largura obtm o caminho mais curto de u at v . O procedimento VisitaBfs contri uma rvore de busca em largura que armazenada na varivel antecessor . O programa abaixo imprime os vrtices do caminho mais curto entre o vrtice origem e outro vrtice qualquer do grafo, a partir do vetor antecessor . obtido na busca em largura.
public void imprimeCaminho ( int origem , int v ) { i f ( origem == v ) System. out . println ( origem ) ; else i f ( this . antecessor [ v] == 1) System. out . println ( "Nao existe caminho de " + origem + " ate " + v ) ; else { imprimeCaminho ( origem , this . antecessor [ v ] ) ; System. out . println ( v ) ; } }

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.5

57

Ordenao Topolgica
Ordenao linear de todos os vrtices, tal que se G contm uma aresta (u, v ) ento u aparece antes de v . Pode ser vista como uma ordenao de seus vrtices ao longo de uma linha horizontal de tal forma que todas as arestas esto direcionadas da esquerda para a direita. Pode ser feita usando a busca em profundidade.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.5

58

Ordenao Topolgica
Os grafos direcionados acclicos so usados para indicar precedncias entre eventos. Uma aresta direcionada (u, v ) indica que a atividade u tem que ser realizada antes da atividade v .
1/18 0 2/15 4/5 3 2 3/14 1 4 6/13 16/17 5 7/12 6 7 8/11 8 9/10 19/20 9

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.5

59

Ordenao Topolgica
Algoritmo para ordenar topologicamente um grafo direcionado acclico G = (V, A): 1. Aplicar a busca em profundidade no grafo G para obter os tempos de trmino t[u] para cada vrtice u. 2. Ao trmino de cada vrtice, insira-o na frente de uma lista linear encadeada. 3. Retornar a lista encadeada de vrtices. A Custo O(|V | + |A|), uma vez que a busca em profundidade tem complexidade de tempo O(|V | + |A|) e o custo para inserir cada um dos |V | vrtices na frente da lista linear encadeada custa O(1).

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.5

60

Ordenao Topolgica Implementao


Basta inserir uma chamada ao mtodo inserePrimeiro no mtodo buscaDfs , logo aps o momento em que o tempo de trmino t[u] obtido e o vrtice pintado de preto . Ao nal, basta retornar a lista obtida.
/ / Insere antes do primeiro item da lista public void inserePrimeiro ( Object item ) { Celula aux = this . primeiro . prox ; this . primeiro . prox = new Celula ( ) ; this . primeiro . prox . item = item ; this . primeiro . prox . prox = aux; }

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.6

61

Componentes Fortemente Conectados


Um componente fortemente conectado de G = (V, A) um conjunto maximal de vrtices C V tal que para todo par de vrtices u e v em C , u e v so mutuamente alcanveis Podemos particionar V em conjuntos Vi , 1 i r, tal que vrtices u e v so equivalentes se e somente se existe um caminho de u a v e um caminho de v a u.
0 1 0 1 0,1,2

(a)

(b)

(c)

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.6

62

Componentes Fortemente Conectados - Algoritmo


Usa o transposto de G, denido GT = (V, AT ), onde AT = {(u, v ) : (v, u) A}, isto , AT consiste das arestas de G com suas direes invertidas. G e GT possuem os mesmos componentes fortemente conectados, isto , u e v so mutuamente alcanveis a partir de cada um em G se e somente se u e v so mutuamente alcanveis a partir de cada um em GT .

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.6

63

Componentes Fortemente Conectados - Algoritmo


1. Aplicar a busca em profundidade no grafo G para obter os tempos de trmino t[u] para cada vrtice u. 2. Obter GT . 3. Aplicar a busca em profundidade no grafo GT , realizando a busca a partir do vrtice de maior t[u] obtido na linha 1. Se a busca em profundidade no alcanar todos os vrtices, inicie uma nova busca em profundidade a partir do vrtice de maior t[u] dentre os vrtices restantes. 4. Retornar os vrtices de cada rvore da oresta obtida na busca em profundidade na linha 3 como um componente fortemente conectado separado.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.6

64

Componentes Fortemente Conectados - Exemplo


A parte (b) apresenta o resultado da busca em profundidade sobre o grafo transposto obtido, mostrando os tempos de trmino e a classicao das arestas. A busca em profundidade em GT resulta na oresta de rvores mostrada na parte (c).
1/8 0 2/7 1 cruz 3 4/5 2 3/6 1/6 0 ret arv 3/4 1 arv ret 0 cruz 3

arv cruz 2 arv 1

3 2 cruz 7/8 2/5

(a)

(b)

(c)

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.6

65

Componentes Fortemente Conectados - Implementao


public Grafo grafoTransposto ( ) { Grafo grafoT = new Grafo ( this .numVertices ) ; for ( int v = 0; v < this .numVertices ; v++) i f ( ! this . listaAdjVazia ( v ) ) { Aresta adj = this . primeiroListaAdj ( v ) ; while ( adj ! = null ) { grafoT . insereAresta ( adj .v2 ( ) , adj .v1 ( ) , adj .peso ( ) ) ; adj = this . proxAdj ( v ) ; } } return grafoT ; }

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.6

66

Componentes Fortemente Conectados - Implementao


package cap7; import cap7. listaadj . autoreferencia .Grafo; public class Cfc { private static class TempoTermino { private int numRestantes, t [ ] ; private boolean restantes [ ] ; public TempoTermino ( int numVertices ) { t = new int [numVertices ] ; restantes = new boolean [numVertices ] ; numRestantes = numVertices; } public int maxTT ( ) { int vMax = 0; while ( ! this . restantes [vMax] ) vMax++; for ( int i = 0; i < this . t . length ; i ++) { i f ( this . restantes [ i ] ) { i f ( this . t [ i ] > this . t [vMax] ) vMax = i ; } } return vMax; } } private Grafo grafo ; public Cfc ( Grafo grafo ) { this . grafo = grafo ; }

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.6

67

Componentes Fortemente Conectados - Implementao


private void visitaDfs ( Grafo grafo , int u, TempoTermino t t ) { t t . restantes [u] = false ; t t .numRestantes ; System. out . println ( " Vertice : "+u) ; i f ( ! grafo . listaAdjVazia (u ) ) { Grafo. Aresta a = grafo . primeiroListaAdj (u) ; while (a ! = null ) { int v = a.v2 ( ) ; i f ( t t . restantes [ v ] ) { this . visitaDfs ( grafo , v , t t ) ; } a = grafo . proxAdj (u) ; } } } public void obterCfc ( ) { BuscaEmProfundidade dfs = new BuscaEmProfundidade ( this . grafo ) ; dfs .buscaEmProfundidade ( ) ; TempoTermino t t = new TempoTermino ( this . grafo .numVertices ( ) ) ; for ( int u = 0; u < this . grafo .numVertices ( ) ; u++) { t t . t [u] = dfs . t (u ) ; t t . restantes [u] = true ; } Grafo grafoT = this . grafo . grafoTransposto ( ) ; while ( t t .numRestantes > 0) { int vRaiz = t t .maxTT ( ) ; System. out . println ( "Raiz da proxima arvore : " + vRaiz ) ; this . visitaDfs ( grafoT , vRaiz , t t ) ; } } }

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.6

68

Componentes Fortemente Conectados - Anlise


Utiliza o algoritmo para busca em profundidade duas vezes, uma em G e outra em GT . Logo, a complexidade total O(|V | + |A|).

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.7

69

rvore Geradora Mnima - Aplicao


Projeto de redes de comunicaes conectando n localidades. Arranjo de n 1 conexes, conectando duas localidades cada. Objetivo: dentre as possibilidades de conexes, achar a que usa menor quantidade de cabos. Modelagem: G = (V, A): grafo conectado, no direcionado. V : conjunto de cidades. A: conjunto de possveis conexes p(u, v ): peso da aresta (u, v ) A, custo total de cabo para conectar u a v . Soluo: encontrar um subconjunto T A que conecta todos os vrtices de G e cujo peso total p(T ) = (u,v)T p(u, v ) minimizado.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.7

70

rvore Geradora Mnima (AGM)


Como G = (V, T ) acclico e conecta todos os vrtices, T forma uma rvore chamada rvore geradora de G. O problema de obter a rvore T conhecido como rvore geradora mnima (AGM). Ex.: rvore geradora mnima T cujo peso total 12. T no nica, pode-se substituir a aresta (3, 5) pela aresta (2, 5) obtendo outra rvore geradora de custo 12.
6 1 5 4 2 6 3 0 1 2 4 5 4 4 3 5 2 5 3 1 2 0 1 2 4 2 3

(a)

(b)

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.7.1

71

AGM - Algoritmo Genrico


Uma estratgia gulosa permite obter a AGM adicionando uma aresta de cada vez. Invariante: Antes de cada iterao, S um subconjunto de uma rvore geradora mnima. A cada passo adicionamos a S uma aresta (u, v ) que no viola o invariante. (u, v ) chamada de uma aresta segura.
void GenericoAGM 1 2 3 4 5 S = ; while ( S no constitui uma rvore geradora mnima) (u, v ) = seleciona (A) ; i f ( aresta (u, v ) segura para S ) S = S + {(u, v )} return S ;

Dentro do while, S tem que ser um subconjunto prprio da AGM T , e assim tem que existir uma aresta (u, v ) T tal que (u, v ) S e (u, v ) seguro para S .

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.7.1

72

AGM - Denio de Corte


Um corte (V , V V ) de um grafo no direcionado G = (V, A) uma partio de V . Uma aresta (u, v ) A cruza o corte (V , V V ) se um de seus vrtices pertence a V e o outro vrtice pertence a V V . Um corte respeita um conjunto S de arestas se no existirem arestas em S que o cruzem. Uma aresta cruzando o corte que tenha custo mnimo sobre todas as arestas cruzando o corte uma aresta leve.
p p V V V 1 5 b 6 2 0 1 2 6 4 4 5 3 4 b 2 5 3 p V V V

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.7.1

73

AGM - Teorema para reconhecer arestas seguras


Seja G = (V, A) um grafo conectado, no direcionado, com pesos p sobre as arestas V . seja S um subconjunto de V que est includo em alguma AGM para G. Seja (V , V V ) um corte qualquer que respeita S . Seja (u, v ) uma aresta leve cruzando (V , V V ). Satisfeitas essas condies, a aresta (u, v ) uma aresta segura para S .

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.7.2

74

AGM - Algoritmo de Prim


O algoritmo de Prim para obter uma AGM pode ser derivado do algoritmo genrico. O subconjunto S forma uma nica rvore, e a aresta segura adicionada a S sempre uma aresta de peso mnimo conectando a rvore a um vrtice que no esteja na rvore. A rvore comea por um vrtice qualquer (no caso 0) e cresce at que gere todos os vrtices em V . A cada passo, uma aresta leve adicionada rvore S , conectando S a um vrtice de GS = (V, S ). De acordo com o teorema anterior, quando o algoritmo termina, as arestas em S formam uma rvore geradora mnima.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.7.2

75

Algoritmo de Prim - Exemplo


(a)
6 1 5 4 2 6 3 0 0 2 1 2 1 6 4 5 4 6 4 3 2 2 1 2 1 4 4 3 0 1 2 4 5 4 4 2 5 3

(b)
6 1

0 0 5 3 2 1 5

(c)

(d)

0 0 2

(e)
2 1

0 0 2 3 2 1 5 4 5 4

(f)
2 1

0 0 2 3 2 1 3 4 5 4

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.7.2

76

Algoritmo de Prim - Heap Indireto


package cap7; public class FPHeapMinIndireto { private double p [ ] ; private int n, pos [ ] , fp [ ] ; public FPHeapMinIndireto ( double p [ ] , int v [ ] ) { this .p = p ; this . fp = v ; this .n = this . fp . length1; this .pos = new int [ this .n ] ; for ( int u = 0; u < this .n ; u++) this .pos[u] = u+1; } public void refaz ( int esq, int dir ) { int j = esq 2 ; int x = this . fp [esq ] ; while ( j <= dir ) { i f ( ( j < dir ) && ( this .p[ fp [ j ] ] > this .p[ fp [ j + 1 ] ] ) ) j ++; i f ( this .p[ x] <= this .p[ fp [ j ] ] ) break ; this . fp [esq] = this . fp [ j ] ; this .pos[ fp [ j ] ] = esq; esq = j ; j = esq 2; } this . fp [esq] = x ; this .pos[ x ] = esq; } public void constroi ( ) { int esq = n / 2 + 1 ; while (esq > 1 ) { esq; this . refaz (esq, this .n ) ; } } public int retiraMin ( ) throws Exception { int minimo; i f ( this .n < 1) throw new Exception ( "Erro : heap vazio" ) ; else { minimo = this . fp [ 1 ] ; this . fp [1] = this . fp [ this .n ] ; this .pos[ fp [ this .n ]] = 1; this . refaz ( 1 , this .n) ; } return minimo; }

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.7.2

77

Algoritmo de Prim - Heap Indireto


public void diminuiChave ( int i , double chaveNova) throws Exception { i = this .pos[ i ] ; int x = fp [ i ] ; i f (chaveNova < 0) throw new Exception ( "Erro : chaveNova com valor incorreto " ) ; this .p[ x ] = chaveNova; while ( ( i > 1) && ( this .p[ x] <= this .p[ fp [ i / 2 ] ] ) ) { this . fp [ i ] = this . fp [ i / 2 ] ; this .pos[ fp [ i / 2 ] ] = i ; i /= 2; } this . fp [ i ] = x ; this .pos[ x ] = i ; } boolean vazio ( ) { return this .n == 0; }

O programa acima apresenta a classe FPHeapMinIndireto com as estruturas de dados e as operaes necessrias para operar com um heap indireto. O arranjo pos [v ] fornece a posio do vrtice v dentro do heap fp, permitindo assim que o vrtice v possa ser acessado a um custo O(1). O acesso ao vrtice v necessrio para a operao diminuiChave .

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.7.2

78

Algoritmo de Prim - Implementao


package cap7; import cap7. listaadj . autoreferencia .Grafo; public class AgmPrim { private int antecessor [ ] ; private double p [ ] ; private Grafo grafo ; public AgmPrim ( Grafo grafo ) { this . grafo = grafo ; } public void obterAgm ( int raiz ) throws Exception { int n = this . grafo .numVertices ( ) ; this .p = new double [n ] ; / / peso dos vrtices int vs [ ] = new int [n+1]; / / vrtices boolean itensHeap [ ] = new boolean [n ] ; this . antecessor = new int [n ] ; for ( int u = 0; u < n ; u ++) { this . antecessor [u] = 1; p[u] = Double. MAX_VALUE ; / / vs[u+1] = u ; / / Heap indireto a ser construdo itensHeap[u] = true ; }

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.7.2

79

Algoritmo de Prim - Implementao


p[ raiz ] = 0; FPHeapMinIndireto heap = new FPHeapMinIndireto ( p, vs ) ; heap. constroi ( ) ; while ( !heap. vazio ( ) ) { int u = heap. retiraMin ( ) ; itensHeap[u] = false ; i f ( ! this . grafo . listaAdjVazia (u ) ) { Grafo. Aresta adj = grafo . primeiroListaAdj (u) ; while ( adj ! = null ) { int v = adj .v2 ( ) ; i f ( itensHeap[ v] && (adj .peso ( ) < this .peso ( v ) ) ) { antecessor [ v ] = u ; heap.diminuiChave ( v , adj .peso ( ) ) ; } adj = grafo . proxAdj (u) ; } } } } public int antecessor ( int u ) { return this . antecessor [u ] ; } public double peso ( int u ) { return this .p[u ] ; } public void imprime ( ) { for ( int u = 0; u < this .p. length ; u++) i f ( this . antecessor [u] != 1) System. out . println ( " ( " +antecessor [u]+ " , " +u+ ") p: " + peso (u) ) ; } }

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.7.2

80

Algoritmo de Prim - Implementao


A classe AgmPrim implementa o algoritmo de Prim, cujo grafo de entrada G fornecido atravs do construtor da classe AgmPrim . O mtodo obterAgm recebe o vrtice raiz como entrada. O campo antecessor [v ] armazena o antecessor de v na rvore. Quando o algoritmo termina, a la de prioridades fp est vazia, e a rvore geradora mnima S para G : S = {(v, antecessor [v ]) : v V {raiz }} Os mtodos pblicos antecessor , peso e imprime so utilizados para permitir ao usurio da classe AgmPrim obter o antecessor de um certo vrtice, obter o peso associado a um vrtice e imprimir as arestas da rvore, respectivamente.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.7.2

81

Algoritmo de Prim - Anlise


O corpo do anel while executado |V | vezes. O mtodo refaz tem custo O(log |V |). Logo, o tempo total para executar a operao retira o item com menor peso O(|V | log |V |). O while mais interno para percorrer a lista de adjacentes O(|A|) (soma dos comprimentos de todas as listas de adjacncia 2|A|). O teste para vericar se o vrtice v pertence ao heap A tem custo O(1). Aps testar se v pertence ao heap e o peso da aresta (u, v ) menor do que p[v ], o antecessor de v armazenado em antecessor [v ] e uma operao diminuiChave realizada sobre o heap na posio pos [v ], a qual tem custo O(log |V |). Logo, o tempo total para executar o algoritmo de Prim O(|V log |V | + |A| log |V |) = O(|A| log |V |).

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.7.3

82

AGM - Algoritmo de Kruskal


Pode ser derivado do algoritmo genrico. S uma oresta e a aresta segura adicionada a S sempre uma aresta de menor peso que conecta dois componentes distintos. Considera as arestas ordenadas pelo peso.
(a)
6 1 5 4 2 6 3 0 1 2 4 5 4 4 5 2 5 3 1 2

(b)
0 3

(c)
0 1 2 4 5 3

(d)
0 1 2 4 5 3

(e)
0 1 2 4 5 3

(f)
0 1 2 4 5 3

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.7.3

83

AGM - Algoritmo de Kruskal


Sejam C1 e C2 duas rvores conectadas por (u, v ): Como (u, v ) tem de ser uma aresta leve conectando C1 com alguma outra rvore, (u, v ) uma aresta segura para C1 . guloso porque, a cada passo, ele adiciona oresta uma aresta de menor peso. Obtm uma AGM adicionando uma aresta de cada vez oresta e, a cada passo, usa a aresta de menor peso que no forma ciclo. Inicia com uma oresta de |V | rvores de um vrtice: em |V | passos, une duas rvores at que exista apenas uma rvore na oresta.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.7.3

84

Algoritmo de Kruskal - Implementao


Usa la de prioridades para obter arestas em ordem crescente de pesos. Testa se uma dada aresta adicionada ao conjunto soluo S forma um ciclo. Tratar conjuntos disjuntos: maneira eciente de vericar se uma dada aresta forma um ciclo. Utiliza estruturas dinmicas. Os elementos de um conjunto so representados por um objeto. Operaes: Criar um novo conjunto cujo nico membro x, o qual passa a ser seu representante. Fazer a unio de dois conjuntos dinmicos cujos representantes so x e y . A operao une os conjuntos dinmicos que contm x e y , digamos Cx e Cy , em um novo conjunto que a unio desses dois conjuntos. Encontrar o conjunto de um dado elemento x. Essa operao retorna uma referncia ao representante do conjunto (nico) contendo x.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.7.3

85

Algoritmo de Kruskal - Implementao


Primeiro renamento:
void Kruskal ( Grafo grafo ) ConjuntoDisjunto conj = new ConjuntoDisjunto ( ) ; 1. 2. 3. 4. 5. 6. 7. S = ; for ( int v=0; v<grafo .numVertices ( ) ; v++) conj . criaConjunto (v ) ; Ordena as arestas de A pelo peso; for (cada ( u, v ) de A tomadas em ordem ascendente de peso) i f ( conj . encontraConjunto (u) ! = conj . encontraConjunto ( v) ) S = S + { (u, v) } ; conj . uniao ( u, v ) ;

A implementao das operaes uniao e encontraConjunto deve ser realizada de forma eciente. Esse problema conhecido na literatura como Unio-EncontraConjunto.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.7.3

86

AGM - Anlise do Algoritmo de Kruskal


A inicializao do conjunto S tem custo O(1). Ordenar arestas (linha 3) custa O(|A| log |A|). A linha 2 realiza |V | operaes criaConjunto . O anel (linhas 4-7) realiza O(|A|) operaes encontraConjunto e uniao , a um custo O((|V | + |A|)(|V |)) onde (|V |) uma funo que cresce lentamente ((|V |) < 4). O limite inferior para construir uma estrutura dinmica envolvendo m operaes encontraConjunto e uniao e n operaes criaConjunto m(n). Como G conectado temos que |A| |V | 1, e assim as operaes sobre conjuntos disjuntos custam O(|A|(|V |). Como (|V |) = O(log |A|) = O(log |V |), o tempo total do algoritmo de Kruskal O(|A| log |A|). Como |A| < |V |2 , ento log |A| = O(log |V |), e o custo do algoritmo de Kruskal tambm O(|A| log |V |).

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.8

87

Caminhos Mais Curtos - Aplicao


Um motorista procura o caminho mais curto entre Diamantina e Ouro Preto. Possui mapa com as distncias entre cada par de intersees adjacentes. Modelagem: G = (V, A): grafo direcionado ponderado, mapa rodovirio. V : intersees. A: segmentos de estrada entre intersees p(u, v ): peso de cada aresta, distncia entre intersees. Peso de um caminho: p(c) = Caminho mais curto: (u, v ) =
c min p(c) : u ; v se existir caminho de u a v caso contrrio
k i=1

p(vi1 , vi )

Caminho mais curto do vrtice u ao vrtice v : qualquer caminho c com peso p(c) = (u, v ).

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.8

88

Caminhos Mais Curtos


Caminhos mais curtos a partir de uma origem: dado um grafo ponderado G = (V, A), desejamos obter o caminho mais curto a partir de um dado vrtice origem s V at cada v V . Muitos problemas podem ser resolvidos pelo algoritmo para o problema origem nica: Caminhos mais curtos com destino nico: reduzido ao problema origem nica invertendo a direo de cada aresta do grafo. Caminhos mais curtos entre um par de vrtices: o algoritmo para origem nica a melhor opo conhecida. Caminhos mais curtos entre todos os pares de vrtices: resolvido aplicando o algoritmo origem nica |V | vezes, uma vez para cada vrtice origem.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.8

89

Caminhos Mais Curtos


A representao de caminhos mais curtos em um grafo G = (V, A) pode ser realizada por um vetor chamado antecessor . Para cada vrtice v V o antecessor [v ] um outro vrtice u V ou null (1). O algoritmo atribui ao antecessor os rtulos de vrtices de uma cadeia de antecessores com origem em v e que anda para trs ao longo de um caminho mais curto at o vrtice origem s. Dado um vrtice v no qual antecessor [v ] = null , o mtodo imprimeCaminho pode imprimir o caminho mais curto de s at v .

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.8

90

Caminhos Mais Curtos


Os valores em antecessor [v ], em um passo intermedirio, no indicam necessariamente caminhos mais curtos. Entretanto, ao nal do processamento, antecessor contm uma rvore de caminhos mais curtos denidos em termos dos pesos de cada aresta de G, ao invs do nmero de arestas. Caminhos mais curtos no so necessariamente nicos.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.8

91

rvore de caminhos mais curtos


Uma rvore de caminhos mais curtos com raiz em u V um subgrafo direcionado G = (V , A ), onde V V e A A, tal que: 1. V o conjunto de vrtices alcanveis a partir de s G, 2. G forma uma rvore de raiz s, 3. para todos os vrtices v V , o caminho simples de s at v um caminho mais curto de s at v em G.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.8

92

Algoritmo de Dijkstra
Mantm um conjunto S de vrtices cujos caminhos mais curtos at um vrtice origem j so conhecidos. Produz uma rvore de caminhos mais curtos de um vrtice origem s para todos os vrtices que so alcanveis a partir de s. Utiliza a tcnica de relaxamento: Para cada vrtice v V o atributo p[v ] um limite superior do peso de um caminho mais curto do vrtice origem s at v . O vetor p[v ] contm uma estimativa de um caminho mais curto. O primeiro passo do algoritmo inicializar os antecessores e as estimativas de caminhos mais curtos: a ntecessor[v ] = n ull para todo vrtice v V, p[u] = 0, para o vrtice origem s, e p[v ] = para v V {s}.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.8

93

Relaxamento
O relaxamento de uma aresta (u, v ) consiste em vericar se possvel melhorar o melhor caminho at v obtido at o momento se passarmos por u. Se isto acontecer, p[v ] e a ntecessor[v ] devem ser atualizados.
i f (p[ v] > p[u] + peso da aresta ( u, v) ) p[ v ] = p[u] + peso da aresta ( u, v ) ; antecessor [ v ] = u;

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.8

94

Algoritmo de Dijkstra - 1o Renamento


dijkstra ( Grafo grafo , int raiz ) 1. 2. 3. 4. 5. 6 7. 8. 9 10. 11. 12. 13. for ( int v = 0; v < grafo .numVertices ( ) ; v++) p[ v ] = I n f i n i t o ; antecessor [ v] = 1; p[ raiz ] = 0; Constroi heap sobre vrtices do grafo ; S = ; while ( !heap. vazio ( ) ) u = heap. retiraMin ( ) ; S = S + u; for ( v grafo . listaAdjacentes (u) ) i f (p[ v] > p[u] + peso da aresta ( u, v) ) p[ v ] = p[u] + peso da aresta ( u, v ) ; antecessor [ v ] = u;

Invariante: o nmero de elementos do heap igual a V S no incio do anel while. A cada iterao do while, um vrtice u extrado do heap e adicionado ao conjunto S , mantendo assim o invariante. A operaoretiraMin obtm o vrtice u com o caminho mais curto estimado at o momento e adiciona ao conjunto S . No anel da linha 10, a operao de relaxamento realizada sobre cada aresta (u, v ) adjacente ao vrtice u.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.8

95

Algoritmo de Dijkstra - Exemplo


(a)
1 1 5 2 1 2 3 0 3 10 4 6

(b)
1 1 1 5 2 1

0 0 3 10 4 6 2 3 3 10

(c)
1 1 5 2 6 1 1

0 0 3 10 4 6 2 3 3 10

Iterao (a) (b) (c)

S {0} {0, 1}

d[0] 0 0

d[1] 1 1

d[2] 6

d[3] 3 3

d[4] 10 10

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.8

96

Algoritmo de Dijkstra - Exemplo


(d)
1 1 5 2 5 1 2 3 1 0 0 3 10 4 6 3 0 1 1 5 2 5 1 2 3 0 3 10 4 6 3 6 9

(e)
1 1 5 2 5 1 1

0 0 3 10 4 6 2 3 3 6

(f)
1

Iterao (d) (e) (f)

S {0, 1, 3} {0, 1, 3, 2} {0, 1, 3, 2, 4}

d[0] 0 0 0

d[1] 1 1 1

d[2] 5 5 5

d[3] 3 3 3

d[4] 9 6 6

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.8

97

Algoritmo de Dijkstra
Para realizar de forma eciente a seleo de uma nova aresta, todos os vrtices que no esto na rvore de caminhos mais curtos residem no heap A baseada no campo p. Para cada vrtice v , p[v ] o caminho mais curto obtido at o momento, de v at o vrtice raiz. O heap mantm os vrtices, mas a condio do heap mantida pelo caminho mais curto estimado at o momento atravs do arranjo p[v ], o heap indireto. o arranjo pos [v ] fornece a posio do vrtice v dentro do heap, permitindo assim que o vrtice v possa ser acessado a um custo O(1) para a operao diminuiChave .

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.8

98

Algoritmo de Dijkstra - Implementao


package cap7; import cap7. listaadj . autoreferencia .Grafo; public class Dijkstra { private int antecessor [ ] ; private double p [ ] ; private Grafo grafo ; public Dijkstra ( Grafo grafo ) { this . grafo = grafo ; } public void obterArvoreCMC ( int raiz ) throws Exception { int n = this . grafo .numVertices ( ) ; this .p = new double [n ] ; / / peso dos vrtices int vs [ ] = new int [n+1]; / / vrtices this . antecessor = new int [n ] ; for ( int u = 0; u < n ; u ++) { this . antecessor [u] = 1; p[u] = Double. MAX_VALUE ; / / vs[u+1] = u ; / / Heap indireto a ser construdo } p[ raiz ] = 0;

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.8

99

Algoritmo de Dijkstra - Implementao


FPHeapMinIndireto heap = new FPHeapMinIndireto ( p, vs ) ; heap. constroi ( ) ; while ( !heap. vazio ( ) ) { int u = heap. retiraMin ( ) ; i f ( ! this . grafo . listaAdjVazia (u ) ) { Grafo. Aresta adj = grafo . primeiroListaAdj (u) ; while ( adj ! = null ) { int v = adj .v2 ( ) ; i f ( this .p[ v] > ( this .p[u] + adj .peso ( ) ) ) { antecessor [ v ] = u; heap.diminuiChave ( v , this .p[u] + adj .peso ( ) ) ; } adj = grafo . proxAdj (u) ; } } } } public int antecessor ( int u ) { return this . antecessor [u ] ; } public double peso ( int u ) { return this .p[u ] ; } public void imprimeCaminho ( int origem , int v ) { i f ( origem == v ) System. out . println ( origem ) ; else i f ( this . antecessor [ v] == 1) System. out . println ( "Nao existe caminho de " +origem+ " ate " +v ) ; else { imprimeCaminho ( origem , this . antecessor [ v ] ) ; System. out . println ( v ) ; } } }

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.8

100

Porque o Algoritmo de Dijkstra Funciona


O algoritmo usa uma estratgia gulosa: sempre escolher o vrtice mais leve (ou o mais perto) em V S para adicionar ao conjunto soluo S , O algorimo de Dijkstra sempre obtm os caminhos mais curtos, pois cada vez que um vrtice adicionado ao conjunto S temos que p[u] = (r aiz, u).

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.9

101

O Tipo Abstrato de Dados Hipergrafo


Um hipergrafo ou rgrafo um grafo no direcionado G = (V, A) no qual cada aresta a A conecta r vrtices, sendo r a ordem do hipergrafo. Os grafos estudados at agora so 2-grafos (ou hipergrafos de ordem 2). So utilizados para auxiliar na obteno de funes de transformao perfeitas mnimas. A forma mais adequada para representar um hipergrafo por meio de listas de incidncia. Em uma representao de um grafo no direcionado usando listas de incidncia, para cada vrtice v do grafo mantida uma lista das arestas que incidem sobre o vrtice v . Essa uma estrutura orientada a arestas e no a vrtices como as representaes. Isso evita a duplicao das arestas ao se representar um grafo no direcionado pela verso direcionada correspondente.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.9

102

O Tipo Abstrato de Dados Hipergrafo


Operaes de um tipo abstrato de dados hipergrafo: 1. Criar um hipergrafo vazio. 2. Inserir uma aresta no hipergrafo. 3. Vericar se existe determinada aresta no hipergrafo. 4. Obter a lista de arestas incidentes em determinado vrtice. 5. Retirar uma aresta do hipergrafo. 6. Imprimir um hipergrafo. 7. Obter o nmero de vrtices do hipergrafo. 8. Obter a aresta de menor peso de um hipergrafo.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.9

103

O Tipo Abstrato de Dados Hipergrafo


Uma operao que aparece com freqncia a de obter a lista de arestas incidentes em determinado vrtice. Para implementar esse operador precisamos de trs operaes sobre hipergrafos, a saber: 1. Vericar se a lista de arestas incidentes em um vrtice v est vazia. 2. Obter a primeira aresta incidente a um vrtice v , caso exista. 3. Obter a prxima aresta incidente a um vrtice v , caso exista.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.9

104

O Tipo Abstrato de Dados Hipergrafo


A estrutura de dados usada para representar o hipergrafo orientada a arestas As arestas so armazenadas em um arranjo chamado arestas . Em cada ndice a do arranjo arestas , so armazenados os r vrtices da aresta a e o seu peso . As listas de arestas incidentes nos vrtices so armazenadas em dois arranjos: prim (ponto de entrada para a lista de arestas incidentes) e prox (as arestas subseqentes). Valores armazenados nos arranjos prim e prox so obtidos pela equao a + i|A|, sendo 0 i r 1 e a um ndice de uma aresta. Para se ter acesso a uma aresta a armazenada em arestas [a] preciso tomar os valores armazenados nos arranjos prim e prox mdulo |A|. O valor 1 utilizado para nalizar a lista. prim deve possuir |V | entradas. prox deve possuir r|A| entradas.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.9

105

O Tipo Abstrato de Dados Hipergrafo Exemplo


Para descobrir quais so as arestas que contm determinado vrtice v preciso percorrer a lista de arestas que inicia em prim [v ] e termina quando prox [. . . prim [v ] . . .] = 1. Exemplo, ao se percorrer a lista das arestas do vrtice 2, os valores {4, 8, 5} so obtidos, os quais representam as arestas que contm o vrtice 2, ou seja, {4 mod 5 = 4, 8 mod 5 = 3, 5 mod 5 = 0}.
(a)
5 2 4 1 3 4 3 2 0 1 0 prim

(b)
arestas

0 1 2 3 4 (1,2,0) (3,4,1) (3,5,2) (0,2,3) (2,3,4) 0 3 1 0 2 4 3 9 4 6 5 7 9 2

0 1 2 3 4 5 6 7 8 prox 1 1 1 1 8 1 1 1 5

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.9

106

O Tipo Abstrato de Dados Hipergrafo Implementao


A varivel r utilizada para armazenar a ordem do hipergrafo. numVertices contm o nmero de vrtices do hipergrafo. proxDisponivel contm a prxima posio disponvel para insero de uma nova aresta. pos utilizado para reter a posio atual na lista de incidncia de um vrtice v .
package cap7. listincidencia ; public class HiperGrafo { public static class Aresta { private int vertices [ ] ; private int peso; public Aresta ( int vertices [ ] , int peso) { this . vertices = vertices ; this .peso = peso; } public int peso ( ) { return this .peso ; } public int vertice ( int i ) { return this . vertices [ i ] ; } public int [ ] vertices ( ) { return this . vertices ; } public boolean equals ( Object aresta ) { Aresta a = ( Aresta) aresta ; i f (a. vertices . length ! = this . vertices . length ) return false ; for ( int i = 0; i < this . vertices . length ; i ++) i f ( this . vertices [ i ] ! = a. vertices [ i ] ) return false ; return true ; }

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.9

107

O Tipo Abstrato de Dados Hipergrafo Implementao


public String toString ( ) { String res = " { " ; int i = 0; for ( i = 0; i < this . vertices . length 1; i ++) res += this . vertices [ i ] + " , " ; res += this . vertices [ i ] + " } ( " + this .peso + " ) " ; return res ; } } private int numVertices , proxDisponivel , r ; private Aresta arestas [ ] ; private int prim [ ] , prox [ ] ; private int pos [ ] ; public HiperGrafo ( int numVertices , int numArestas, int r ) { this . arestas = new Aresta [numArestas] ; this . prim = new int [numVertices ] ; for ( int i = 0; i < numVertices ; i ++) this . prim [ i ] = 1; this . prox = new int [ r numArestas] ; this .numVertices = numVertices; this . proxDisponivel = 0; this . r = r ; this .pos = new int [numVertices ] ; }

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.9

108

O Tipo Abstrato de Dados Hipergrafo Implementao


public void insereAresta ( int vertices [ ] , int peso) { i f ( this . proxDisponivel == this . arestas . length ) System. out . println ( "Nao ha espaco disponivel para a aresta" ) ; else { int a = this . proxDisponivel++; int n = this . arestas . length ; this . arestas [a] = new Aresta ( vertices , peso) ; for ( int i = 0; i < this . r ; i ++) { int ind = a + i n; this . prox [ ind ] = this . prim [ this . arestas [a ] . vertices [ i ] ] ; this . prim [ this . arestas [a ] . vertices [ i ] ] = ind ; } } } public boolean existeAresta ( int vertices [ ] ) { for ( int v = 0; v < this . r ; v++) for ( int i = this . prim [ vertices [ v ] ] ; i != 1; i = this . prox [ i ] ) { int a = i % this . arestas . length ; i f ( this . arestas [a ] . equals (new Aresta ( vertices , 0 ) ) ) return true ; } return false ; }

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.9

109

O Tipo Abstrato de Dados Hipergrafo Implementao


public boolean listaIncVazia ( int v ) { return ( this . prim [ v] == 1); } public Aresta primeiraListaInc ( int v ) { / / Retorna a primeira aresta incidente no vrtice v ou / / null se a lista de arestas incidentes em v for vazia this .pos[ v ] = this . prim [ v ] ; int a = this .pos[ v] % this . arestas . length ; i f (a >= 0) return this . arestas [a ] ; else return null ; } public Aresta proxInc ( int v ) { / / Retorna a prxima aresta incidente no vrtice v ou null / / se a lista de arestas incidentes em v estiver no m this .pos[ v ] = this . prox [ this .pos[ v ] ] ; int a = this .pos[ v] % this . arestas . length ; i f (a >= 0) return this . arestas [a ] ; else return null ; } public Aresta retiraAresta ( int vertices [ ] ) { int n = this . arestas . length , a = 0; Aresta aresta = null ; for ( int i = 0; i < this . r ; i ++) { int prev = 1, aux = this . prim [ vertices [ i ] ] ; a = aux % n ; aresta = new Aresta ( vertices , 0 ) ; while ( (aux >= 0) && (! this . arestas [a ] . equals ( aresta ) ) ) { prev = aux ; aux = this . prox [aux ] ; a = aux % n ; } i f (aux >= 0) { / / achou i f ( prev == 1) this . prim [ vertices [ i ] ] = this . prox [aux ] ; else this . prox [ prev ] = this . prox [aux ] ; aresta = this . arestas [a ] ; } else return null ; / / no achou } this . arestas [a] = null ; / / Marca como removido return aresta ; }

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.9

110

O Tipo Abstrato de Dados Hipergrafo Implementao


public void imprime ( ) { for ( int i = 0; i < this .numVertices ; i ++) { System. out . println ( " Vertice " + i + " : " ) ; for ( int j = this . prim [ i ] ; j != 1; j = this . prox [ j ] ) { int a = j % this . arestas . length ; System. out . println ( " } } public int numVertices ( ) { return this .numVertices ; } } a : " + this . arestas [a ] ) ; }

Вам также может понравиться