You are on page 1of 38

Projeto de Algoritmos Cap.

7 Algoritmos em Grafos

Aplicaes

Projeto de Algoritmos Cap.7 Algoritmos em Grafos

Motivao

Alguns exemplos de problemas prticos que podem ser resolvidos


atravs de uma modelagem em grafos:

Muitas aplicaes em computao necessitam considerar conjunto de


conexes entre pares de objetos:

Ajudar mquinas de busca a localizar informao relevante na Web.

Existe um caminho para ir de um objeto a outro seguindo as


conexes?

Descobrir os melhores casamentos entre posies disponveis em


empresas e pessoas que aplicaram para as posies de interesse.

Qual a menor distncia entre um objeto e outro objeto?

Descobrir qual o roteiro mais curto para visitar as principais


cidades de uma regio turstica.

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

Contedo do Captulo
7.1 Definies Bsicas

7.5 Busca em Largura

7.2 O Tipo Abstrato de Dados Grafo

7.6 Ordenao Topolgica

7.2.1 Implementao por meio de Matrizes de Adjacncia

7.7 Componentes Fortemente Conectados

7.2.2 Implementao por meio de Listas de Adjacncia Usando Apontadores

7.8.1 Algoritmo Genrico para Obter a


rvore Geradora Mnima

7.2.3 Implementao por meio de Listas de Adjacncia Usando Arranjos


7.2.4 Programa Teste para as Trs Implementaes
7.3 Busca em Profundidade
7.4 Verificar se Grafo Acclico
7.4.1 Usando Busca em Profundidade
7.4.1 Usando o Tipo Abstrato de Dados Hipergrafo

Algoritmos em Grafos

7.8 rvore Geradora Mnima

7.8.2 Algoritmo de Prim


7.8.2 Algoritmo de Kruskal
7.9 Caminhos mais Curtos
7.10 O Tipo Abstrato de Dados Hipergrafo
ltima alterao: 24 de Setembro de 2010

7.10.1 Implementao por meio de Matrizes de Incidncia


7.10.1 Implementao por meio de Listas
de Incidncia Usando Arranjos
Transparncias

elaboradas por Charles Ornelas Almeida, Israel Guerra e Nivio Ziviani

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.1

Grau de um Vrtice

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.1

Grafos No Direcionados

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.

Um grafo no direcionado G um par (V, A), onde o conjunto de


arestas A constitudo de pares de vrtices no ordenados.
0

As arestas (u, v) e (v, u) so consideradas como uma nica aresta.


A relao de adjacncia simtrica.
Self-loops no so permitidos.

Ex.: O vrtice 1 tem grau 2 e o vrtice


3 isolado.

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, outdegree 2 e grau 4.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.1

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.1

Conceitos Bsicos

Grafos Direcionados
Um grafo direcionado G um par (V, A), onde V um conjunto finito
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.

Grafo: conjunto de vrtices e arestas.


Vrtice: objeto simples que pode ter nome e outros atributos.
Aresta: conexo entre dois vrtices.
3

Podem existir arestas de um vrtice para ele mesmo, chamadas de


self-loops.

0
0

aresta
1

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

11

Componentes Conectados

10

Ciclos

Um grafo no direcionado conectado se cada par de vrtices est


conectado por um caminho.

Em um grafo no direcionado:
Um caminho (v0 , v1 , . . . , vk ) forma um ciclo se v0 = vk e o caminho
contm pelo menos trs arestas.

Os componentes conectados so as pores conectadas de um grafo.

O ciclo simples se os vrtices v1 , v2 , . . . , vk so distintos.

Um grafo no direcionado conectado se ele tem exatamente um


componente conectado.
Ex.: Os componentes so: {0, 1, 2}, {4, 5}
e {3}.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.1

Ex.: O caminho (0, 1, 2, 0) um ciclo.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.1

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.1

Caminho entre Vrtices

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.

Um caminho de comprimento k de um vrtice x a um vrtice y em um


grafo G = (V, A) uma sequncia 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, 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).

Ex.: O caminho (0, 1, 2, 3) simples e tem


comprimento 3. O caminho (1, 3, 0, 3) no
simples.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.1

15

Verso Direcionada de um Grafo No Direcionado

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 }.

Cada aresta no direcionada (u, v) em G substituda por duas


arestas direcionadas (u, v) e (v, u)

Ex.: Subgrafo induzido pelo conjunto de vrtices {1, 2, 4, 5}.

Em um grafo direcionado, um vizinho de um vrtice u qualquer


vrtice adjacente a u na verso no direcionada de G.
1

14

Subgrafos

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.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.1

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.1

13

Grafos Isomorfos

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.1

12

Componentes Fortemente Conectados

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 .

Um grafo direcionado G = (V, A) fortemente conectado se cada


dois vrtices quaisquer so alcanveis a partir um do outro.

Em outras palavras, possvel re-rotular os vrtices de G para serem


rtulos de G mantendo as arestas correspondentes em G e G .

Os componentes fortemente conectados de um grafo direcionado


so conjuntos de vrtices sob a relao so mutuamente
alcanveis.

1
4

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.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.1

19

rvores

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.1

18

Grafos Completos

rvore livre: grafo no direcionado acclico e conectado. comum


dizer apenas que o grafo uma rvore omitindo o livre.

Um grafo completo um grafo no direcionado no qual todos os pares


de vrtices so adjacentes.

Floresta: grafo no direcionado acclico, podendo ou no ser


conectado.

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).

rvore geradora de um grafo conectado G = (V, A): subgrafo que


contm todos os vrtices de G e forma uma rvore.

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).

Floresta geradora de um grafo G = (V, A): subgrafo que contm


todos os vrtices de G e forma uma floresta.

(a)

(b)

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.1

Outras Classificaes 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.

17

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.1

16

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 6= 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.

Hipergrafos so utilizados na Seo 5.5.4 sobre hashing perfeito.


Na Seo 7.10 apresentada uma estrutura de dados mais
adequada para representar um hipergrafo.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2

23

Implementao da Operao Obter Lista de Adjacentes

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2

22

Operao Obter Lista de Adjacentes

comum encontrar um pseudo comando do tipo:

1. ListaAdjVazia(v, Grafo): retorna true se a lista de adjacentes de v est


vazia.

for u ListaAdjacentes (v) do { faz algo com u }

2. PrimeiroListaAdj(v, Grafo): retorna o endereo do primeiro vrtice na


lista de adjacentes de v.

O trecho de programa abaixo apresenta um possvel refinamento do


pseudo comando acima.

3. ProxAdj(v, Grafo, u, Peso, Aux, FimListaAdj): retorna o vrtice u


(apontado por Aux) da lista de adjacentes de v, bem como o peso da
aresta (v, u). Ao retornar, Aux aponta para o prximo vrtice da lista
de adjacentes de v, e FimListaAdj retorna true se o final da lista de
adjacentes foi encontrado.

i f ( ! ListaAdjVazia(v,Grafo) )
{ Aux = PrimeiroListaAdj (v,Grafo ) ;
FimListaAdj = FALSE ;
while ( ! FimListaAdj)
ProxAdj(&v , Grafo, &u, &Peso, &Aux, &FimListaAdj ) ;
}

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2

Operadores do TAD Grafo


1. FGVazio(Grafo): Cria um grafo vazio.

21

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2

O Tipo Abstratos de Dados Grafo

2. InsereAresta(V1,V2,Peso, Grafo): Insere uma aresta no grafo.

Importante considerar os algoritmos em grafos como tipos abstratos


de dados.

3. ExisteAresta(V1,V2,Grafo): Verifica se existe uma determinada aresta.

Conjunto de operaes associado a uma estrutura de dados.

4. Obtem a lista de vrtices adjacentes a um determinado vrtice (tratada


a seguir).

Independncia de implementao para as operaes.

5. RetiraAresta(V1,V2,Peso, Grafo): Retira uma aresta do grafo.


6. LiberaGrafo(Grafo): Liberar o espao ocupado por um grafo.
7. ImprimeGrafo(Grafo): Imprime um grafo.
8. GrafoTransposto(Grafo,GrafoT): Obtm o transposto de um grafo
direcionado.
9. RetiraMin(A): Obtm a aresta de menor peso de um grafo com peso
nas arestas.

20

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.1

27

Matriz de Adjacncia: Estrutura de Dados

26

Matriz de Adjacncia: Anlise


Deve ser utilizada para grafos densos, onde |A| prximo de |V |2 .

A insero de um novo vrtice ou retirada de um vrtice j existente


pode ser realizada com custo constante.

O tempo necessrio para acessar um elemento independente de |V |


ou |A|.

#define MAXNUMVERTICES 100


#define MAXNUMARESTAS 4500

muito til para algoritmos em que necessitamos saber com rapidez


se existe uma aresta ligando dois vrtices.

typedef int TipoValorVertice ;


typedef int

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.1

A maior desvantagem que a matriz necessita (|V |2 ) de espao. Ler


ou examinar a matriz tem complexidade de tempo O(|V |2 ).

TipoPeso;

typedef struct TipoGrafo {


TipoPeso Mat[ MAXNUMVERTICES + 1][MAXNUMVERTICES + 1];
int NumVertices;
int NumArestas;
} TipoGrafo ;
typedef int

TipoApontador;

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.1

25

Matriz de Adjacncia: Exemplo

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.1

Matriz de Adjacncia

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)

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.

24

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.1

31

Matriz de Adjacncia: Operadores

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.1

30

Matriz de Adjacncia: Operadores

/ Operadores para obter a l i s t a de adjacentes /

/ Operadores para obter a l i s t a de adjacentes /

void ProxAdj( TipoValorVertice Vertice , TipoGrafo Grafo,

TipoApontador PrimeiroListaAdj ( TipoValorVertice Vertice , TipoGrafo Grafo)

TipoValorVertice Adj , TipoPeso Peso,

{ TipoValorVertice Result ;

TipoApontador Prox , short FimListaAdj)

TipoApontador Aux = 0;

{ / Retorna Adj apontado por Prox /

short ListaVazia = TRUE ;

Adj = Prox;

while (Aux < Grafo>NumVertices && ListaVazia )

Peso = Grafo>Mat[ Vertice ] [ Prox ] ;

{ i f ( Grafo>Mat[ Vertice ] [Aux] > 0 ) { Result = Aux; ListaVazia = FALSE ; }

(Prox)++;

else Aux++;

while (Prox < Grafo>NumVertices &&

Grafo>Mat[ Vertice ] [ Prox] == 0) (Prox)++;

i f (Aux == Grafo>NumVertices)

i f (Prox == Grafo>NumVertices) FimListaAdj = TRUE ;

p r i n t f ( "Erro : Lista adjacencia vazia ( PrimeiroListaAdj ) \n" ) ;

return Result ;
}

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.1

29

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.1

Matriz de Adjacncia: Operadores

Matriz de Adjacncia: Operadores

/ Operadores para obter a l i s t a de adjacentes /

void FGVazio(TipoGrafo Grafo)

short ListaAdjVazia( TipoValorVertice Vertice , TipoGrafo Grafo)

{ short i , j ;

{ TipoApontador Aux = 0;

for ( i = 0; i <= Grafo>NumVertices ; i ++)

short ListaVazia = TRUE ;


while (Aux < Grafo>NumVertices && ListaVazia )

{ for ( j = 0; j <=Grafo>NumVertices ; j ++) Grafo>Mat[ i ] [ j ] = 0 ; }


}

i f ( Grafo>Mat[ Vertice ] [Aux] > 0) ListaVazia = FALSE ;


else Aux++;
return ( ListaVazia == TRUE ) ;
}

void InsereAresta( TipoValorVertice V1, TipoValorVertice V2,


TipoPeso Peso, TipoGrafo Grafo)
{ Grafo>Mat[V1] [ V2] = Peso; }
short ExisteAresta ( TipoValorVertice Vertice1 ,
TipoValorVertice Vertice2 , TipoGrafo Grafo)
{ return ( Grafo>Mat[ Vertice1 ] [ Vertice2 ] > 0 ) ; }

28

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.2

35

Listas de Adjacncia Usando Apontadores (1)

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.2

34

Listas de Adjacncia Usando Apontadores: Anlise

#define MAXNUMVERTICES 100

Os vrtices de uma lista de adjacncia so em geral armazenados em


uma ordem arbitrria.

#define MAXNUMARESTAS 4500


typedef int TipoValorVertice ;

Possui uma complexidade de espao O(|V | + |A|)

typedef int TipoPeso;


typedef struct TipoItem {
TipoValorVertice Vertice ;

Indicada para grafos esparsos, onde |A| muito menor do que |V |2 .

TipoPeso Peso;

compacta e usualmente utilizada na maioria das aplicaes.

} TipoItem ;

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.

typedef struct TipoCelula TipoApontador;


struct TipoCelula {
TipoItem Item ;
TipoApontador Prox;
} TipoCelula ;

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.2

33

Matriz de Adjacncia: Operadores

Listas de Adjacncia Usando Apontadores


3

5
0

1
7

void RetiraAresta ( TipoValorVertice V1, TipoValorVertice V2,

1 5
1 3

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.1

TipoPeso Peso, TipoGrafo Grafo)


2 7

{ i f ( Grafo>Mat[V1] [ V2] == 0) p r i n t f ( "Aresta nao existe \n" ) ;


else { Peso = Grafo>Mat[V1] [ V2] ; Grafo>Mat[V1] [ V2] = 0 ; }

}
3

3
0

5
0

1
7

void LiberaGrafo(TipoGrafo Grafo)


{

1 5
0 5

/ Nao faz nada no caso de matrizes de adjacencia / }

void ImprimeGrafo(TipoGrafo Grafo)


2 7

{ short i , j ; p r i n t f ( "

" );

for ( i = 0; i <= Grafo>NumVertices 1; i ++) p r i n t f ( "%3d" , i ) ;

1 7

p r i n t f ( " \n" ) ;
3

for ( i = 0; i <= Grafo>NumVertices 1; i ++)


{ p r i n t f ( "%3d" , i ) ;

Um arranjo Adj de |V | listas, uma para cada vrtice em V .

for ( j = 0; j <=Grafo>NumVertices 1; j ++)


p r i n t f ( "%3d" , Grafo>Mat[ i ] [ j ] ) ;

Para cada u V , Adj[u] contm os vrtices adjacentes a u em G.

p r i n t f ( " \n" ) ;
}
}

32

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.2

39

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.2

Listas de Adjacncia Usando Apontadores: Operadores

Listas de Adjacncia usando Apontadores

/ Operadores para obter a l i s t a de adjacentes /

short ExisteAresta ( TipoValorVertice Vertice1 ,

short ListaAdjVazia( TipoValorVertice Vertice , TipoGrafo Grafo)

TipoValorVertice Vertice2 ,

{ return ( Grafo>Adj[ Vertice ] . Primeiro == Grafo>Adj[ Vertice ] . Ultimo ) ;

TipoGrafo Grafo)

38

{ TipoApontador Aux;
short EncontrouAresta = FALSE ;

TipoApontador PrimeiroListaAdj ( TipoValorVertice Vertice , TipoGrafo Grafo)

Aux = Grafo>Adj [ Vertice1 ] . Primeiro>Prox;

{ return ( Grafo>Adj[ Vertice ] . Primeiro>Prox ) ; }

while (Aux ! = NULL && EncontrouAresta == FALSE)


{ i f ( Vertice2 == Aux>Item . Vertice ) EncontrouAresta = TRUE ;

void ProxAdj( TipoValorVertice Vertice , TipoGrafo Grafo,

Aux = Aux>Prox;

TipoValorVertice Adj , TipoPeso Peso,

TipoApontador Prox , short FimListaAdj)

return EncontrouAresta ;

{ / Retorna Adj e Peso do Item apontado por Prox /

Adj = (Prox)>Item . Vertice ;


Peso = (Prox)>Item .Peso;
Prox = (Prox)>Prox;
i f (Prox == NULL) FimListaAdj = TRUE ;
}

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.2

37

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.2

Listas de Adjacncia Usando Apontadores: Operadores

Listas de Adjacncia Usando Apontadores (2)

/ Entram aqui os operadores FLVazia, Vazia, Insere, Retira e Imprime/

typedef struct TipoLista {

/ do TAD Lista de Apontadores do Programa 3.4

TipoApontador Primeiro , Ultimo ;

void FGVazio(TipoGrafo Grafo)

} TipoLista ;

{ long i ;

typedef struct TipoGrafo {

for ( i = 0; i < Grafo>NumVertices ; i ++) FLVazia(&Grafo>Adj [ i ] ) ;


}

TipoLista Adj [ MAXNUMVERTICES + 1];


TipoValorVertice NumVertices;
short NumArestas;

void InsereAresta( TipoValorVertice V1, TipoValorVertice V2,

} TipoGrafo ;

TipoPeso Peso, TipoGrafo Grafo)


{ TipoItem x ;
x . Vertice = V2;
x .Peso = Peso;
Insere(&x, &Grafo>Adj[V1] ) ;
}

No uso de apontadores a lista constituda de clulas, onde cada


clula contm um item da lista e um apontador para a clula seguinte.

36

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.3

43

Listas de Adjacncia Usando Arranjos


3
5
0

V
7

0
1
2
3
4
5
6

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.2

42

Listas de Adjacncia Usando Apontadores: Operadores

Cab

Prox

4
6
2
3
1
1
2

4
5
0
0
0
6
0

Peso

5
3
7

Cab

Prox

Peso

4
6
7
3
1
0
2
1

4
5
7
0
0
6
0
0

void ImprimeGrafo(TipoGrafo Grafo)


{ int i ;
TipoApontador Aux;
for ( i = 0; i < Grafo>NumVertices ; i ++)
{ p r i n t f ( " Vertice%2d: " , i ) ;
i f ( ! Vazia(Grafo>Adj [ i ] ) )
{ Aux = Grafo>Adj [ i ] . Primeiro>Prox;

5
0

1
7

0
1
2
3
4
5
6
7

while (Aux ! = NULL)


{ p r i n t f ( "%3d (%d) " , Aux>Item . Vertice , Aux>Item .Peso) ;
Aux = Aux>Prox;
}

5
5
7
7

}
putchar( \n ) ;
}
}

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)

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.2

41

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.2

Listas de Adjacncia Usando Apontadores: Operadores

Listas de Adjacncia Usando Apontadores: Operadores

void LiberaGrafo(TipoGrafo Grafo)

void RetiraAresta ( TipoValorVertice V1, TipoValorVertice V2,


TipoPeso Peso, TipoGrafo Grafo)

{ TipoApontador AuxAnterior , Aux;


for ( i = 0; i < GRAfo>NumVertices ; i ++)

{ TipoApontador AuxAnterior , Aux;


short EncontrouAresta = FALSE ;

{ Aux = Grafo>Adj [ i ] . Primeiro>Prox;


free (Grafo>Adj [ i ] . Primeiro ) ;

TipoItem x ;

/Libera celula cabeca/

Grafo>Adj [ i ] . Primeiro=NULL ;

AuxAnterior = Grafo>Adj[V1] . Primeiro ;

while (Aux ! = NULL)

Aux = Grafo>Adj[V1] . Primeiro>Prox;


while (Aux ! = NULL && EncontrouAresta == FALSE)

{ AuxAnterior = Aux;

{ i f (V2 == Aux>Item . Vertice )

Aux = Aux>Prox;

{ Retira (AuxAnterior, &Grafo>Adj[V1] , &x ) ;

free (AuxAnterior ) ;

Grafo>NumArestas;

EncontrouAresta = TRUE ;

Grafo>NumVertices = 0;

AuxAnterior = Aux;

Aux = Aux>Prox;
}
}

40

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.3

47

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.3

Listas de Adjacncia Usando Arranjos: Operadores

Listas de Adjacncia Usando Arranjos: Operadores

/ Operadores para obter a l i s t a de adjacentes /

short ExisteAresta ( TipoValorVertice Vertice1 ,

short ListaAdjVazia( TipoValorVertice Vertice , TipoGrafo Grafo)

46

TipoValorVertice Vertice2 , TipoGrafo Grafo)

{ return ( Grafo>Prox[ Vertice ] = = 0 ) ; }

{ TipoApontador Aux;
short EncontrouAresta = FALSE ;

TipoApontador PrimeiroListaAdj ( TipoValorVertice Vertice ,

Aux = Grafo>Prox[ Vertice1 ] ;

TipoGrafo Grafo)

while (Aux != 0 && EncontrouAresta == FALSE)

{ return ( Grafo>Prox[ Vertice ] ) ; }

{ i f ( Vertice2 == Grafo>Cab[Aux] )
EncontrouAresta = TRUE ;

void ProxAdj( TipoValorVertice Vertice , TipoGrafo Grafo,

Aux = Grafo>Prox[Aux] ;

TipoValorVertice Adj , TipoPeso Peso,

TipoApontador Prox , short FimListaAdj)

return EncontrouAresta ;

{ / Retorna Adj apontado por Prox /


Adj = Grafo>Cab[Prox ] ;

Peso = Grafo>Peso[Prox ] ;

Prox = Grafo>Prox[Prox ] ;
i f (Prox == 0) FimListaAdj = TRUE ;
}

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.3

45

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.3

Listas de Adjacncia Usando Arranjos: Operadores

Listas de Adjacncia Usando Arranjos

void FGVazio(TipoGrafo Grafo)

#define MAXNUMVERTICES 100

{ short i ;

#define MAXNUMARESTAS 4500

for ( i = 0; i <= Grafo>NumVertices ; i ++)


{ Grafo>Prox[ i ] = 0 ; Grafo>Cab[ i ] = i ;
Grafo>ProxDisponivel = Grafo>NumVertices;

#define TRUE 1
#define FALSE 0
#define MAXTAM ( MAXNUMVERTICES + MAXNUMARESTAS 2)

}
}

typedef int TipoValorVertice ;

void InsereAresta( TipoValorVertice V1, TipoValorVertice V2,

typedef int TipoPeso;

TipoPeso Peso, TipoGrafo Grafo)


{ short Pos;

typedef struct TipoGrafo {

Pos = Grafo>ProxDisponivel ;

TipoTam Cab[ MAXTAM + 1];

i f ( Grafo>ProxDisponivel == MAXTAM)

TipoTam Prox[ MAXTAM + 1];

{ p r i n t f ( "nao ha espaco disponivel para a aresta \n" ) ; return ; }

TipoTam Peso[ MAXTAM + 1];

Grafo>ProxDisponivel++;

TipoTam ProxDisponivel ;

Grafo>Prox[Grafo>Cab[V1] ] = Pos;

char NumVertices;

Grafo>Cab[Pos] = V2;

Grafo>Cab[V1] = Pos;

Grafo>Prox[Pos] = 0 ; Grafo>Peso[Pos] = Peso;


}

typedef int TipoTam;

short NumArestas;
} TipoGrafo ;
typedef short TipoApontador;

44

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.3

51

Busca em Profundidade

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.3

50

Busca em Profundidade

Para acompanhar o progresso do algoritmo cada vrtice colorido de


branco, cinza ou preto.

A busca em profundidade, do ingls depth-first search), um algoritmo


para caminhar no grafo.

Todos os vrtices so inicializados branco.

A estratgia buscar o mais profundo no grafo sempre que possvel.

Quando um vrtice descoberto pela primeira vez ele torna-se cinza,


e tornado preto quando sua lista de adjacentes tenha sido
completamente examinada.

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.

d[v]: tempo de descoberta


t[v]: tempo de trmino do exame da lista de adjacentes de v.

O algoritmo a base para muitos outros algoritmos importantes, tais


como verificao de grafos acclicos, ordenao topolgica e
componentes fortemente conectados.

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.2.3

49

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.2.3

48

Listas de Adjacncia Usando Arranjos: Operadores

Listas de Adjacncia Usando Arranjos: Operadores

void LiberaGrafo(TipoGrafo Grafo)

void RetiraAresta ( TipoValorVertice V1, TipoValorVertice V2,

/ Nao faz nada no caso de posicoes contiguas / }

TipoPeso Peso, TipoGrafo Grafo)


{ TipoApontador Aux, AuxAnterior ;

short EncontrouAresta = FALSE ;

void ImprimeGrafo(TipoGrafo Grafo)

AuxAnterior = V1; Aux = Grafo>Prox[V1] ;

{ short i , forlim ;

while (Aux != 0 && EncontrouAresta == FALSE)

printf ( "

Cab Prox Peso\n" ) ;

{ i f (V2 == Grafo>Cab[Aux] ) EncontrouAresta = TRUE ;

forlim = Grafo>NumVertices + Grafo>NumArestas 2;

else { AuxAnterior = Aux; Aux = Grafo>Prox[Aux] ; }

for ( i = 0; i <= forlim 1; i ++)

}
i f ( EncontrouAresta ) / Apenas marca como retirado /

p r i n t f ( "%2d%4d%4d%4d\n" , i , Grafo>Cab[ i ] ,

{ Grafo>Cab[Aux] = MAXNUMVERTICES + MAXNUMARESTAS 2;

Grafo>Prox[ i ] , Grafo>Peso[ i ] ) ;
}

}
else p r i n t f ( "Aresta nao existe \n" ) ;
}

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.3

55

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.3

54

Busca em Profundidade: Exemplo

Busca em Profundidade: Anlise


Os dois anis da BuscaEmProfundidade tm custo O(|V |) cada um, a
menos da chamada do procedimento VisitaDfs(u) no segundo anel.

b( / )

b( / )

c(1/ )

b( / )

c(1/ )

c(2/ )

b( / )
b( / ) 2

O procedimento VisitaDfs chamado exatamente uma vez para cada


vrtice u V , desde que VisitaDfs chamado apenas para vrtices
brancos e a primeira ao pintar o vrtice de cinza.

b( / )
b( / ) 2

(a)

Durante a execuo de VisitaDfs(u) o anel principal executado


|Adj[u]| vezes.

(b)

c(2/ )

c(1/ )

c(2/ )

c(1/ )

p(2/5)

b( / )

Desde que uV |Adj[u]| = O(|A|), o tempo total de execuo de


VisitaDfs O(|A|).
P

b( / )
p(3/4) 2

(d)

(e)

p(2/5)

p(1/6)

p(2/5)

p(1/6)

p(2/5)

(g)

53

c(7/ )
p(3/4) 2

p(7/8)
p(3/4) 2

(h)

(i)

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.3

Busca em Profundidade: Implementao

Busca em Profundidade: Implementao

void BuscaEmProfundidade(TipoGrafo Grafo)

void VisitaDfs ( TipoValorVertice u, TipoGrafo Grafo,

{ TipoValorVertice x ;

TipoValorTempo Tempo, TipoValorTempo d,

TipoValorTempo Tempo;
TipoValorTempo d[ MAXNUMVERTICES + 1] , t [ MAXNUMVERTICES + 1];

(f)

b( / )

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.3

b( / )
p(3/4) 2

p(1/6)

p(3/4) 2

(c)

c(1/ )

c(3/ ) 2

Logo, a complexidade total da BuscaEmProfundidade O(|V | + |A|).

b( / )
b( / ) 2

TipoValorTempo t , TipoCor Cor, short Antecessor)


{ char FimListaAdj ; TipoValorAresta Peso; TipoApontador Aux;

TipoCor Cor[ MAXNUMVERTICES+1];

TipoValorVertice v ; Cor[u] = cinza ; ( Tempo)++; d[u] = (Tempo) ;

short Antecessor[ MAXNUMVERTICES+1];

p r i n t f ( " Visita%2d Tempo descoberta:%2d cinza \n" , u, d[u ] ) ; getchar ( ) ;

Tempo = 0;

i f ( ! ListaAdjVazia(&u, Grafo) )

for ( x = 0; x <= Grafo>NumVertices 1; x++)

{ Aux = PrimeiroListaAdj(&u, Grafo ) ; FimListaAdj = FALSE ;

{ Cor[ x ] = branco;

while ( ! FimListaAdj)

Antecessor[ x] = 1;

{ ProxAdj(&u, &v, &Peso, &Aux, &FimListaAdj ) ;

i f (Cor[ v] == branco)

for ( x = 0; x <= Grafo>NumVertices 1; x++)

{ Antecessor[ v ] = u ; VisitaDfs (v , Grafo , Tempo, d, t , Cor, Antecessor ) ;

{ i f (Cor[ x] == branco)

VisitaDfs (x , Grafo, &Tempo, d, t , Cor, Antecessor ) ;

}
Cor[u] = preto ; ( Tempo)++; t [u] = (Tempo) ;

p r i n t f ( " Visita%2d Tempo termino:%2d preto \n" , u, t [u ] ) ; getchar ( ) ;


}

52

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.4.2

59

Teste para Verificar se Grafo Acclico


Usando o Tipo Abstrato de Dados Hipergrafo

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.4.1

Teste para Verificar se Grafo Acclico


Usando Busca em Profundidade

Hipergrafos ou rgrafos Gr (V, A) so apresentados na Seo 7.10


(Slide 119).

A busca em profundidade pode ser usada para verificar se um grafo


acclico ou contm um ou mais ciclos.

Representao: por meio de estruturas de dados orientadas a arestas


em que para cada vrtice v do grafo mantida uma lista das arestas
que incidem sobre o vrtice v.

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.

Existem duas representaes usuais para hipergrafos: matrizes de


incidncia e listas de incidncia. Aqui utilizaremos a implementao
de listas de incidncia usando arranjos apresentada na Seo 7.10.2.

O algoritmo BuscaEmProfundidade pode ser alterado para descobrir


arestas de retorno. Para isso, basta verificar se um vrtice v adjacente
a um vrtice u apresenta a cor cinza na primeira vez que a aresta
(u, v) percorrida.

O programa a seguir utiliza a seguinte propriedade de r-grafos:


Um r-grafo acclico se e somente se a remoo repetida de
arestas contendo apenas vrtices de grau 1 (vrtices sobre os
quais incide apenas uma aresta) elimina todas as arestas do grafo.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.3.1

Na busca em profundidade cada aresta pode ser classificada pela cor


do vrtice que alcanado pela primeira vez:
Branco indica uma aresta de rvore.
Preto indica uma aresta de avano quando u descoberto antes de
v ou uma aresta de cruzamento caso contrrio.
2/9

arv

ret

arv

1/10
arv

cruz

avan
3
4/5

cruz

4
7/8

cruz

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).

Cinza indica uma aresta de retorno.

arv

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.3.1

Classificao de Arestas

Classificao de arestas pode ser til para derivar outros algoritmos.

3/6

O algoritmo tem custo linear no nmero de vrtices e de arestas de um


grafo G = (V, A) que pode ser utilizado para verificar se G acclico.

57

Classificao de Arestas

5
11/12

58

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.

56

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.4.2

63

Teste para Verificar se Grafo Acclico


Usando o Tipo Abstrato de Dados Hipergrafo (2)

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.4.2

62

Teste para Verificar se Grafo Acclico


Usando o Tipo Abstrato de Dados Hipergrafo (1)

i f ( Grafo>Prim[ x .Chave] >= 0)

void GrafoAciclico ( TipoGrafo Grafo,

{ A1 = Grafo>Prim[ x .Chave] % Grafo>NumArestas;

TipoArranjoArestas L, short GAciclico )

Aresta = RetiraAresta(&Grafo>Arestas [A1] , Grafo ) ;

{ TipoValorVertice j = 0; TipoValorAresta A1;

L[Grafo>NumArestas NArestas] = Aresta ;

TipoItem x ; TipoFila Fila ; TipoValorAresta NArestas;

NArestas = NArestas 1;

TipoAresta Aresta ; NArestas = Grafo>NumArestas;

i f ( NArestas > 0)

FFVazia (& Fila ) ;

{ for ( j = 0; j < Grafo>r ; j ++)

while ( j < Grafo>NumVertices)

{ i f (VerticeGrauUm(&Aresta . Vertices [ j ] , Grafo) )

{ i f (VerticeGrauUm (& j , Grafo) )

{ x .Chave = Aresta . Vertices [ j ] ; Enfileira ( x, & Fila ) ;

{ x .Chave = j ; Enfileira ( x, & Fila ) ; }

j ++;

while ( ! Vazia(&Fila ) && (NArestas > 0))

{ Desenfileira (& Fila , &x ) ;

}
i f ( NArestas == 0) GAciclico = TRUE ;
else GAciclico = FALSE ;
}

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.4.2

61

Teste para Verificar se Grafo Acclico


Usando o Tipo Abstrato de Dados Hipergrafo

Teste para Verificar se Grafo Acclico


Usando o Tipo Abstrato de Dados Hipergrafo

program GrafoAciclico ;

O procedimento a seguir recebe o grafo e retorna no vetor L as arestas


retiradas do grafo na ordem em foram retiradas.

/ Entram aqui os tipos do Programa 3.17 (ou do Programa 3.19 /


/ Entram aqui tipos do Programa 7.25 ( Slide 137) /
int i , j ;

O procedimento primeiro procura os vrtices de grau 1 e os coloca em


uma fila. A seguir, enquanto a fila no estiver vazia, desenfileira um
vrtice e retira a aresta incidente ao vrtice.

TipoAresta Aresta ;
TipoGrafo Grafo;
TipoArranjoArestas L;
short GAciclico ;
/ Entram aqui os operadores FFVazia, Vazia , Enfileira e

/ Desenfileira do Programa 3.18 (ou do Programa 3.20

/ Entram aqui os operadores ArestasIguais , FGVazio, InsereAresta ,


/ RetiraAresta e ImprimeGrafo do Programa 7.26 ( Slide 138 )

short VerticeGrauUm( TipoValorVertice V,


TipoGrafo Grafo)
{ return ( Grafo>Prim[V] >= 0) && (Grafo>Prox[Grafo>Prim[V]] == INDEFINIDO ) ;
}

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.4.2

Se a aresta retirada tinha algum outro vrtice de grau 2, ento esse


vrtice muda para grau 1 e enfileirado.
Se ao final no restar nenhuma aresta, ento o grafo acclico. O
custo do procedimento GrafoAciclico O(|V | + |A|).

60

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.5

67

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.5

Busca em Largura: Implementao

Busca em Largura: Implementao

/ Entram aqui os operadores FFVazia, Vazia, Enfileira e Desenfileira do /

void BuscaEmLargura(TipoGrafo Grafo)

/ do Programa 3.18 ou do Programa 3.20, dependendo da implementao /

{ TipoValorVertice x ;

/ da busca em largura usar arranjos ou apontadores, respectivamente /

int Dist [MaxNumvertices + 1];

void VisitaBfs ( TipoValorVertice u, TipoGrafo Grafo,

TipoCor Cor[MaxNumvertices + 1];

int Dist , TipoCor Cor, int Antecessor)


{ TipoValorVertice v ;

Apontador Aux;

TipoPeso Peso;

TipoItem Item ;

Cor[u] = cinza ;

Dist [u] = 0;

int Antecessor[MaxNumvertices + 1];


for ( x = 0; x <= Grafo > NumVertices 1; x++)

short FimListaAdj ;

{ Cor[ x ] = branco ; Dist [ x ] = I n f i n i t o ; Antecessor[ x] = 1; }

TipoFila Fila ;

for ( x = 0; x <= Grafo > NumVertices 1; x++)

FFVazia(&Fila ) ;
Item . Vertice = u ;

66

{ i f (Cor[ x] == branco)
Item .Peso = 0;

VisitaBfs ( x , Grafo , Dist , Cor, Antecessor ) ;

Enfileira (Item, & Fila ) ;

p r i n t f ( " Visita origem %2d cor : cinza F: " , u) ;

ImprimeFila( Fila ) ; getchar ( ) ;

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.5

Busca em Largura
Cada vrtice colorido de branco, cinza ou preto.
Todos os vrtices so inicializados branco.

65

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.5

Busca em Largura
Expande a fronteira entre vrtices descobertos e no descobertos
uniformemente atravs da largura da fronteira.

Quando um vrtice descoberto pela primeira vez ele torna-se cinza.

O algoritmo descobre todos os vrtices a uma distncia k do vrtice


origem antes de descobrir qualquer vrtice a uma distncia k + 1.

Vrtices cinza e preto j foram descobertos, mas so distinguidos para


assegurar que a busca ocorra em largura.

O grafo G(V, A) pode ser direcionado ou no direcionado.

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.

64

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.5

71

Caminhos Mais Curtos

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.5

70

Busca em Largura: Anlise (Para Listas de Adjacncia)

A busca em largura obtm o caminho mais curto de u at v.

O custo de inicializao do primeiro anel em BuscaEmLargura


O(|V |) cada um.

O procedimento VisitaBfs contri uma rvore de busca em largura que


armazenada na varivel Antecessor.

O custo do segundo anel tambm O(|V |).

O programa a seguir imprime os vrtices do caminho mais curto entre


o vrtice origem e outro vrtice qualquer do grafo.

VisitaBfs: enfileirar e desenfileirar tm custo O(1), logo, o custo total


com a fila O(|V |).

void ImprimeCaminho( TipoValorVertice Origem, TipoValorVertice v,

Cada lista de adjacentes percorrida no mximo uma vez, quando o


vrtice desenfileirado.

TipoGrafo Grafo , int Dist , TipoCor Cor,


int Antecessor)
{ i f (Origem == v ) { p r i n t f ( "%d " , Origem) ; return ; }

Desde que a soma de todas as listas de adjacentes O(|A|), o tempo


total gasto com as listas de adjacentes O(|A|).

i f ( Antecessor[ v] == 1)
p r i n t f ( "Nao existe caminho de %d ate %d" , Origem, v ) ;
else { ImprimeCaminho(Origem,Antecessor[ v ] , Grafo , Dist , Cor, Antecessor ) ;

Complexidade total: O(|V | + |A|).

p r i n t f ( "%d " , v ) ;
}
}

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.5

69

Busca em Largura: Exemplo


c(0)

b( )

b( )

4
F 0
0

(a)

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.5

Busca em Largura: Implementao


p(0)

c(1)

b( )

while ( ! FilaVazia ( Fila ) )


{ Desenfileira(&Fila , &Item ) ;

F 1 3
1 1

(b)

b( )

b( )

b( )

c(1)

b( )

b( )

p(0)

p(1)

b( )

p(0)

p(1)

b( )

c(1)

c(2)

b( )

p(1)

c(2)

b( )

u = Item . Vertice ;
i f ( ! ListaAdjVazia(&u, Grafo) )
{ Aux = PrimeiroListaAdj(&u, Grafo ) ;

F 3 2
1 2

(c)

FimListaAdj = FALSE ;
while ( FimListaAdj == FALSE)

F 2
2

(d)

{ ProxAdj(&u, &v, &Peso, &Aux, &FimListaAdj ) ;


i f (Cor[ v ] ! = branco ) continue;
Cor[ v ] = cinza ;

p(0)

p(1)

b( )

4
F

(e)

p(0)

p(1)

c(0)

Item .Peso = Peso; Enfileira (Item, & Fila ) ;

F 4
0

(f)

p(1)

p(2)

b( )

p(1)

p(2)

b( )

Dist [ v ] = Dist [u] + 1;

Antecessor[ v ] = u ; Item . Vertice = v ;


}
}
Cor[u] = preto ;

p(0)

p(1)

p(0)

p(0)

p(1)

p(0)

F 5
1

(g)

p r i n t f ( " Visita %2d Dist %2d cor : preto F: " , u, Dist [u ] ) ;


ImprimeFila( Fila ) ; getchar ( ) ;

(h)

p(1)

p(2)

c(1)

p(1)

p(2)

p(1)

}
}

/ VisitaBfs /

68

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.6

75

Ordenao Topolgica: Implementao

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.6

74

Ordenao Topolgica

Basta inserir uma chamada para o procedimento InsLista no


procedimento BuscaDfs, logo aps o momento em que o tempo de
trmino t[u] obtido e o vrtice pintado de preto.

Algoritmo para ordenar topologicamente um grafo direcionado acclico


G = (V, A):
1. Chama BuscaEmProfundidade(G) para obter os tempos de trmino
t[u] para cada vrtice u.

Ao final, basta retornar a lista obtida (ou imprim-la usando o


procedimento Imprime do Programa 3.4).

2. Ao trmino de cada vrtice insira-o na frente de uma lista linear


encadeada.

void InsLista ( TipoItem Item , TipoLista Lista )

3. Retorna a lista encadeada de vrtices.

{ / Insere antes do primeiro item da l i s t a /


TipoApontador Aux;

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).

Aux = Lista>Primeiro>Prox;
Lista>Primeiro>Prox = (TipoApontador)malloc(sizeof( tipoCelula ) ) ;
Lista>Primeiro>Prox>Item = Item ;
Lista>Primeiro>Prox>Prox = Aux;
}

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.6

73

Ordenao Topolgica

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

16/17

4/5 3

19/20
7/12

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.

6/13

8/11

Ordenao linear de todos os vrtices, tal que se G contm uma


aresta (u, v) ento u aparece antes de v.

2/15

3/14

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.6

9/10

72

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.7

79

Componentes Fortemente Conectados: Exemplo

1. Chama BuscaEmProfundidade(G) para obter os tempos de trmino


t[u] para cada vrtice u.
2. Obtem GT .

A busca em profundidade em GT resulta na floresta de rvores


mostrada na parte (c).
2/7

1/6

0
cruz

3
4/5

2
3/6

(a)

ret
arv

cruz

3. Chama BuscaEmProfundidade(GT ), realizando a busca a partir do


vrtice de maior t[u] obtido na linha 1. Inicie uma nova busca em
profundidade a partir do vrtice de maior t[u] dentre os vrtices
restantes se houver.

arv cruz

1
arv

3
2
cruz
7/8
2/5

(b)

3/4

ret

78

Componentes Fortemente Conectados: Algoritmo

A parte (b) apresenta o resultado da busca em profundidade sobre o


grafo transposto obtido, mostrando os tempos de trmino e a
classificao das arestas.

1/8

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.7

4. Retorne os vrtices de cada rvore da floresta obtida como um


componente fortemente conectado separado.

2
arv
1

(c)

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.7

Componentes Fortemente Conectados: Algoritmo

77

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.7

76

Componentes Fortemente Conectados

Usa o transposto de G, definido GT = (V, AT ), onde


AT = {(u, v) : (v, u) A}, isto , AT consiste das arestas de G com
suas direes invertidas.

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

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 .

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

0,1,2

(a)

(b)

(c)

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.7

83

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.7

82

Componentes Fortemente Conectados: Implementao

Componentes Fortemente Conectados: Implementao

void VisitaDfs2 ( TipoValorVertice u, TipoGrafo Grafo,

void BuscaEmProfundidadeCfc(TipoGrafo Grafo , TipoTempoTermino TT)

TipoTempoTermino TT , TipoValorTempo Tempo,

{ TipoValorTempo Tempo;

TipoValorTempo d, TipoValorTempo t ,

TipoValorTempo d[ MAXNUMVERTICES + 1] , t [ MAXNUMVERTICES + 1];

TipoCor Cor, short Antecessor)


{ short FimListaAdj ; TipoPeso Peso; TipoApontador Aux;

TipoCor Cor[ MAXNUMVERTICES + 1];


short Antecessor[ MAXNUMVERTICES + 1];

TipoValorVertice v ;

Cor[u] = cinza ;

TipoValorVertice x , VRaiz ; Tempo = 0;

(Tempo)++; d[u] = (Tempo) ;

for ( x = 0; x <= Grafo>NumVertices 1; x++)


{ Cor[ x ] = branco ; Antecessor[ x] = 1; }

TT>Restantes[u] = FALSE ;
TT>NumRestantes ;

TT>NumRestantes = Grafo>NumVertices;

p r i n t f ( " Visita%2d Tempo descoberta:%2d cinza \n" ,u,d[u ] ) ;

for ( x = 0; x <= Grafo>NumVertices 1; x++)


TT>Restantes[ x ] = TRUE ;

getchar ( ) ;

while ( TT>NumRestantes > 0)


{ VRaiz = MaxTT(TT , Grafo ) ;
p r i n t f ( "Raiz da proxima arvore:%2d\n" , VRaiz) ;
VisitaDfs2 (VRaiz, Grafo , TT, &Tempo,

d, t ,Cor, Antecessor ) ;

}
}

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.7

81

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.7

Componentes Fortemente Conectados: Implementao

Componentes Fortemente Conectados: Implementao

typedef struct TipoTempoTermino {

void GrafoTransposto(TipoGrafo Grafo , TipoGrafo GrafoT)

TipoValorTempo t [ MAXNUMVERTICES + 1];

{ TipoValorVertice v , Adj ;

short Restantes[ MAXNUMVERTICES + 1];

TipoPeso Peso;

TipoValorVertice NumRestantes;

TipoApontador Aux;

} TipoTempoTermino;

FGVazio(GrafoT) ;

TipoValorVertice MaxTT(TipoTempoTermino TT , TipoGrafo Grafo)

GrafoT>NumArestas = Grafo>NumArestas;

{ TipoValorVertice Result ; short i = 0 , Temp;

for ( v = 0; v <= Grafo>NumVertices 1; v++)

GrafoT>NumVertices = Grafo>NumVertices;

{ i f ( ! ListaAdjVazia(&v , Grafo) )

while ( ! TT>Restantes[ i ] ) i ++;

{ Aux = PrimeiroListaAdj(&v , Grafo ) ;

Temp = TT>t [ i ] ; Result = i ;


for ( i = 0; i <= Grafo>NumVertices 1; i ++)

FimListaAdj = FALSE ;
while ( ! FimListaAdj)

{ i f ( TT>Restantes[ i ] )

{ ProxAdj(&v , Grafo, &Adj, &Peso, &Aux, &FimListaAdj ) ;

{ i f (Temp < TT>t [ i ] ) { Temp = TT>t [ i ] ; Result = i ; }

InsereAresta(&Adj, &v, &Peso, GrafoT) ;

}
}

}
}

return Result ;
}

}
}

BuscaEmProfundidadeCfc utiliza MaxTT para obter o vrtice de maior

80

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.8

87

rvore Geradora Mnima

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.8

86

rvore Geradora Mnima

Como G = (V, T ) acclico e conecta todos os vrtices, T forma uma


rvore chamada rvore geradora de G.

Projeto de redes de comunicaes conectando n localidades.


Arranjo de n 1 conexes, conectando duas localidades cada.

O problema de obter a rvore T conhecido como rvore geradora


mnima (AGM).

Objetivo: dentre as possibilidades de conexes, achar a que usa


menor quantidade de cabos.

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.

Modelagem:
G = (V, A): grafo conectado, no direcionado.
V : conjunto de cidades.

6
1

5
3

2
5
4

A: conjunto de possveis conexes


2

p(u, v): peso da aresta (u, v) A, custo total de cabo para conectar
u a v.

2
4

(a)

Soluo: encontrar um subconjunto T A, acclico, que conecta todos


P
os vrtices de G e cujo peso total p(T ) = (u,v)T p(u, v) minimizado.

(b)

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.7

Componentes Fortemente Conectados: Anlise

85

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.7

Componentes Fortemente Conectados: Implementao


i f ( ! ListaAdjVazia(&u, Grafo) )

Utiliza o algoritmo para busca em profundidade duas vezes, uma em G


e outra em GT .

{ Aux = PrimeiroListaAdj(&u, Grafo ) ;


FimListaAdj = FALSE ;
while ( ! FimListaAdj)

Logo, a complexidade total O(|V | + |A|).

{ ProxAdj(&u, Grafo, &v, &Peso, &Aux, &FimListaAdj ) ;


i f (Cor[ v] == branco)
{ Antecessor[ v ] = u;
VisitaDfs2 ( v , Grafo , TT , Tempo, d, t , Cor, Antecessor ) ;
}
}
}
Cor[u] = preto ; ( Tempo)++;
t [u] = (Tempo) ;
p r i n t f ( " Visita%2d Tempo termino:%2d preto \n" , u, t [u ] ) ;
getchar ( ) ;
}

84

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.8.2

91

Algoritmo de Prim para Obter Uma AGM

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.8.1

90

AGM - Teorema para Reconhecer Arestas Seguras

O algoritmo de Prim para obter uma AGM pode ser derivado do


algoritmo genrico.

Considere G = (V, A) um grafo conectado, no direcionado, com


pesos p sobre as arestas V .

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.

Considere S um subconjunto de V que est includo em alguma AGM


para G.
Considere (V , V V ) um corte qualquer que respeita S.

A rvore comea por um vrtice qualquer (no caso 0) e cresce at que


gere todos os vrtices em V .

Considere (u, v) uma aresta leve cruzando (V , V V ).


Satisfeitas essas condies, (u, v) uma aresta segura para S.

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.8.1

89

AGM - Definio de Corte

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.8.1

AGM - Algoritmo Genrico


void GenericoAGM( )

Um corte (V , V V ) de um grafo no direcionado G = (V, A) uma


partio de V .

1{ S = ;

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 .

while(S no constitui uma rvore geradora mnima)

{ ( u, v ) = seleciona(A) ;

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
0

p
V

V V

5
2

p
3

V V

2
4
b

6 4
5
3

4
5

i f ( aresta ( u, v ) segura para S ) S = S+ { ( u, v ) } }


return S ;

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.
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) 6 S e (u, v)
seguro para S.

88

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.8.2

95

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.8.2

94

Prim: Operadores para Manter o Heap Indireto (3)

Prim: Operadores para Manter o Heap Indireto (2)

void DiminuiChaveInd( TipoIndice i , TipoPeso ChaveNova, TipoItem A,

TipoItem RetiraMinInd(TipoItem A, TipoPeso P, TipoValorVertice Pos)

TipoPeso P, TipoValorVertice Pos)

{ TipoItem Result ;

{ TipoItem x ;

i f (n < 1 ) { p r i n t f ( "Erro : heap vazio \n" ) ; return Result ; }

i f (ChaveNova > P[A[ i ] .Chave] )

Result = A[ 1 ] ; A[1] = A[n ] ;

{ p r i n t f ( "Erro : ChaveNova maior que a chave atual \n" ) ;

Pos[A[n ] .Chave] = 1 ; n;

return ;

RefazInd(1 , n, A, P, Pos ) ;

return Result ;

P[A[ i ] .Chave] = ChaveNova;

while ( i > 1 && P[A[ i / 2 ] .Chave] > P[A[ i ] .Chave] )


{ x = A[ i / 2 ] ; A[ i / 2 ] = A[ i ] ;
Pos[A[ i ] .Chave] = i / 2 ; A[ i ] = x ;
Pos[ x .Chave] = i ; i /= 2;
}
}

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.8.2

Prim: Operadores para Manter o Heap Indireto (1)


/ Entra aqui o operador Constroi da Seo 4.1.5 (Programa 4.10) /
/ Trocando a chamada Refaz (Esq, n , A) por RefazInd (Esq, n, A) /

93

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.8.2

92

Algoritmo de Prim: Exemplo


(a)

(b)
0

void RefazInd( TipoIndice Esq, TipoIndice Dir , TipoItem A,


TipoPeso P, TipoValorVertice Pos)

while ( j <= Dir )

5
1

(d)

A[ i ] = A[ j ] ; Pos[A[ j ] .Chave] = i ; i = j ;

2
1
5

2
1

Pos[ x .Chave] = i ;
}

(f)

2
1

2
1

2
1
4

2
1
6

j = i 2;
L999: A[ i ] = x ;

(e)

2
1

i f (P[ x .Chave] <= P[A[ j ] .Chave] ) goto L999;

2
1

{ i f ( j < Dir )
{ i f (P[A[ j ] .Chave] > P[A[ j +1].Chave] ) j ++; }

0
0

{ TipoIndice i = Esq; int j = i 2 ; TipoItem x ; x = A[ i ] ;

(c)

0
0

2
1
5

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.8.2

99

Algoritmo de Prim: Anlise

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.8.2

98

Algoritmo de Prim: Implementao

O corpo do anel while executado |V | vezes.


O procedimento Refaz tem custo O(log |V |).

Para realizar de forma eficiente a seleo de uma nova aresta, todos


os vrtices que no esto na AGM residem no heap A.

Logo, o tempo total para executar a operao retira o item com menor
peso O(|V | log |V |).

O heap contm os vrtices, mas a condio do heap mantida pelo


peso da aresta atravs do arranjo p[v] (heap indireto).

O while mais interno para percorrer a lista de adjacentes O(|A|)


(soma dos comprimentos de todas as listas de adjacncia 2|A|).

Pos[v] fornece a posio do vrtice v dentro do heap A, para que o


vrtice v possa ser acessado a um custo O(1), necessrio para a
operao DiminuiChave.

O teste para verificar se o vrtice v pertence ao heap A custa O(1).


Aps testar se v pertence ao heap A e o peso da aresta (u, v) menor
do que p[v], o antecessor de v armazenado em Antecessor e uma
operao DiminuiChave realizada sobre o heap A na posio Pos[v],
a qual tem custo O(log |V |).

Antecessor[v] armazena o antecessor de v na rvore.


Quando o algoritmo termina, A est vazia e a AGM est de forma
implcita como S = {(v, Antecessor [v]) : v V {Raiz }}

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.8.2

Algoritmo de Prim: Implementao

97

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.8.2

Algoritmo de Prim: Implementao

while (n >= 1) /enquanto heap nao vazio/

{ Entram aqui operadores do tipo grafo do Slide 28 ou Slide 37 ou Slide 45, }

{ TEMP = RetiraMinInd(A, P, Pos) ;

{ e os operadores RefazInd , RetiraMinInd e DiminuiChaveInd do Slide 93 }

u = TEMP.Chave; Itensheap [u] = FALSE ;

void AgmPrim(TipoGrafo Grafo , TipoValorVertice Raiz)

i f (u != Raiz)

{ int

p r i n t f ( "Aresta de arvore : v[%d ] v[%d] " ,u,Antecessor[u ] ) ; getchar ( ) ;


i f ( ! ListaAdjVazia(&u, Grafo) )

Vetor A;

{ Aux = PrimeiroListaAdj(&u, Grafo ) ;

TipoPeso P[ MAXNUMVERTICES + 1];

FimListaAdj = FALSE ;

TipoValorVertice Pos[ MAXNUMVERTICES + 1 ] , u, v ;

while ( ! FimListaAdj)

TipoItem TEMP;

{ ProxAdj(&u, Grafo, &v, &Peso, &Aux, &FimListaAdj ) ;

for (u = 0; u <= Grafo>NumVertices ; u++)

i f ( Itensheap [ v] && Peso < P[ v ] )

DiminuiChaveInd(Pos[ v ] , Peso, A, P, Pos) ;

A[u+1].Chave = u ;

}
}
}
}

/Constroi o heap com todos os valores igual a INFINITO/


Antecessor[u] = 1; P[u] = INFINITO ;

{ Antecessor[ v ] = u;

Antecessor[ MAXNUMVERTICES + 1];

short Itensheap [ MAXNUMVERTICES + 1];

/Heap a ser construido/

Itensheap [u] = TRUE ; Pos[u] = u + 1;


}
n = Grafo>NumVertices ; P[Raiz] = 0;
Constroi(A, P, Pos) ;

96

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.8.3

103

Algoritmo de Kruskal: Implementao

Usa fila de prioridades para obter arestas em ordem crescente de


pesos.

void Kruskal ( ) ;

Testa se uma aresta adicionada ao conjunto soluo S forma um ciclo.

{
1. S = ;

Tratar conjuntos disjuntos: maneira eficiente de verificar se uma


dada aresta forma um ciclo. Utiliza estruturas dinmicas.

2. for (v=0;v < Grafo.NumVertices) CriaConjunto ( v ) ;


3. Ordena as arestas de A pelo peso;

Os elementos de um conjunto so representados por um objeto.


Operaes:

4. for (cada ( u, v ) de A tomadas em ordem ascendente de peso)


i f ( EncontreConjunto (u) ! = EncontreConjunto ( v ) )

6.

{ S = S+ { (u, v ) } ;

7.

CriaConjunto(x): cria novo conjunto cujo nico membro, x, seu


representante. Para que os conjuntos sejam disjuntos, x no pode
pertencer a outro conjunto.

Uniao ( u, v ) ;
}

Unio(x, y): une conjuntos dinmicos contendo x (Cx ) e y (Cy ) em


novo conjunto, cujo representante pode ser x ou y. Como os
conjuntos na coleo devem ser disjuntos, Cx e Cy so destrudos.

A implementao das operaes Unio e EncontraConjunto deve ser


realizada de forma eficiente.

EncontreConjunto(x): retorna apontador para o representante do


conjunto (nico) contendo x.

Esse problema conhecido na literatura como Unio-EncontraConjunto.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.8.3

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 floresta uma aresta de
menor peso.

102

Algoritmo de Kruskal: Implementao

Primeiro refinamento:

5.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.8.3

101

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.8.3

100

AGM - Algoritmo de Kruskal


Pode ser derivado do algoritmo genrico.
S uma floresta 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)

(b)
0

Obtm uma AGM adicionando uma aresta de cada vez floresta e, a


cada passo, usa a aresta de menor peso que no forma ciclo.

(c)
0

5
3

2
5

Inicia com uma floresta de |V | rvores de um vrtice: em |V | passos,


une duas rvores at que exista apenas uma rvore na floresta.

3
2

(d)

(e)
0

2
5

(f)

2
4

6
4

2
5

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.9

107

Caminhos Mais Curtos

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.9

106

Caminhos Mais Curtos

A representao de caminhos mais curtos pode ser realizada pela varivel


Antecessor.

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 .

Para cada vrtice v V o Antecessor [v] um outro vrtice u V ou nil (-1).


O algoritmo atribui a 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.

Muitos problemas podem ser resolvidos pelo algoritmo para o


problema origem nica:

Dado um vrtice v no qual Antecessor [v] 6= nil , o procedimento


ImprimeCaminho pode imprimir o caminho mais curto de s at v.

Caminhos mais curtos com destino nico: reduzido ao problema


origem nica invertendo a direo de cada aresta do grafo.

Os valores em Antecessor [v], em um passo intermedirio, no indicam


necessariamente caminhos mais curtos.

Caminhos mais curtos entre um par de vrtices: o algoritmo


para origem nica a melhor opo conhecida.

Entretanto, ao final do processamento, Antecessor contm uma rvore de


caminhos mais curtos definidos em termos dos pesos de cada aresta de G,
ao invs do nmero de arestas.

Caminhos mais curtos entre todos os pares de vrtices:


resolvido aplicando o algoritmo origem nica |V | vezes, uma vez
para cada vrtice origem.

Caminhos mais curtos no so necessariamente nicos.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.9

105

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:

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.

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) =

Pk

i=1 p(vi1 , vi )

Caminho mais curto:


(u, v) =

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.8.3

n
o
c
min p(c) : u ;
v

se existir caminho de u a v
caso contrrio

Caminho mais curto do vrtice u ao vrtice v: qualquer caminho c com peso


p(c) = (u, v).

O anel (linhas 4-7) realiza O(|A|) operaes EncontreConjunto 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 EncontreConjunto 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 |).

104

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.9

111

Algoritmo de Dijkstra: 1o Refinamento

O relaxamento de uma aresta (u, v) consiste em verificar se


possvel melhorar o melhor caminho at v obtido at o momento se
passarmos por u.

{
1. for (v=0;v < Grafo.NumVertices; v++)
p[ v ] = I n f i n i t o ;

3.

Antecessor[ v] = 1;

110

Relaxamento

void Dijkstra (Grafo , Raiz)

2.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.9

Se isto acontecer, p[v] e Antecessor[v] devem ser atualizados.

4. p[Raiz] = 0;
i f (p[ v] > p[u] + peso da aresta ( u, v) )

5. Constroi heap no vetor A;

{ p[ v ] = p[u] + peso da aresta ( u, v ) ;

6. S = ;

Antecessor[ v ] = u ; }

7. while (heap > 1)


8.

u = RetiraMin(A) ;

9.

S = S + u;

10. for ( v ListaAdjacentes [u] )


11.

i f (p[ v] > p[u] + peso da aresta (u, v) )

12.

p[ v ] = p[u ]

13.

Antecessor[ v ] = u;

+ peso da aresta (u, v ) ;

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.9

Algoritmo de Dijkstra
Mantm um conjunto S de vrtices cujos caminhos mais curtos at um
vrtice origem j so conhecidos.

109

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.9

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:

Produz uma rvore de caminhos mais curtos de um vrtice origem s


para todos os vrtices que so alcanveis a partir de s.

1. V o conjunto de vrtices alcanveis a partir de s G,

Utiliza a tcnica de relaxamento:

3. para todos os vrtices v V , o caminho simples de s at v um


caminho mais curto de s at v em G.

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:
Antecessor[v] = nil para todo vrtice v V ,
p[u] = 0, para o vrtice origem s, e
p[v] = para v V {s}.

2. G forma uma rvore de raiz s,

108

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.9

115

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.9

Algoritmo de Dijkstra: Exemplo

Algoritmo de Dijkstra

(a)

Para realizar de forma eficiente 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.

(b)

(b)

10
4

3
1

5
2

6
2

(d)

1
1

1
2

5
2

10

Iterao

d[0]

d[1]

(a)

(b)

{0}

(c)

{0, 1}

6
2

3
1

3
3

0
0

10

6
2

6
4

6
2

(f)

10
4

10

10

0
1

10

Iterao

d[0]

d[1]

d[2]

d[3]

d[4]

(d)

{0, 1, 3}

(e)

{0, 1, 3, 2}

(f)

{0, 1, 3, 2, 4}

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.9

1
1

10

1
2

6
4

6
2

d[2]

d[3]

d[4]

10

10

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.

10
4

10

10

0
1

(f)

10

10

(e)

(c)

0
1

10

Algoritmo de Dijkstra: 1o Refinamento

Algoritmo de Dijkstra: Exemplo


0

(e)

10

(c)

0
1

113

6
2

(d)

1
2

O arranjo Pos[v] fornece a posio do vrtice v dentro do heap A,


permitindo assim que o vrtice v possa ser acessado a um custo O(1)
para a operao DiminuiChaveInd.

10

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.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.9

Para cada vrtice v, p[v] o caminho mais curto obtido at o momento,


de v at o vrtice raiz.

(a)

114

RetiraMin 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.

112

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.10

119

O Tipo Abstrato de Dados Hipergrafo

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,

Os grafos estudados at agora so 2-grafos (hipergrafos de ordem 2).

O algorimo de Dijkstra sempre obtm os caminhos mais curtos, pois


cada vez que um vrtice adicionado ao conjunto S temos que
p[u] = (Raiz, u).

Hipergrafos so utilizados na Seo 5.5.4 sobre hashing perfeito.


A figura apresenta um 3-grafo contendo os vrtices {0, 1, 2, 3, 4, 5}, as
arestas {(1, 2, 4), (1, 3, 5), (0, 2, 5)} e os pesos 7, 8 e 9,
respectivamente.

1
11
00
00
11
00
11
00
11
0
1
00
11
3
0
1
00
11
0
1
0
1
0
1
0
1
5
0
1

h0 (x)

Arestas

h1 (x)

1
0
0 (1, 3, 5, 8)
1

(1, 2, 4, 7)

(0, 2, 5, 9)

h2 (x)

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.9

Algoritmo de Dijkstra: Implementao

117

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.9

Algoritmo de Dijkstra: Implementao

i f ( ! ListaAdjVazia(&u, Grafo) )

/ Entram aqui os operadores de uma das implementaes de grafos, bem como o operador Constroi da implementao de filas de prioridades, assim como os operadores RefazInd, RetiraMinInd e DiminuiChaveInd do Programa Constroi /
void Dijkstra (TipoGrafo Grafo , TipoValorVertice Raiz)

{ Aux = PrimeiroListaAdj(&u, Grafo ) ; FimListaAdj = FALSE ;

{ TipoPeso P[ MAXNUMVERTICES + 1];

while (n >= 1) /enquanto heap nao vazio/


{ temp = RetiraMinInd(A, P, Pos) ;
u = temp.Chave; Itensheap [u] = FALSE ;

while ( ! FimListaAdj)

TipoValorVertice Pos[ MAXNUMVERTICES + 1];

{ ProxAdj(&u, Grafo, &v, &Peso, &Aux, &FimListaAdj ) ;

long Antecessor[ MAXNUMVERTICES + 1];

i f (P[ v] > (P[u] + Peso) )

short Itensheap [ MAXNUMVERTICES + 1];

{ P[ v ] = P[u] + Peso; Antecessor[ v ] = u;

TipoVetor A; TipoValorVertice u, v ; TipoItem temp;

DiminuiChaveInd(Pos[ v ] , P[ v ] , A, P, Pos) ;

for (u = 0; u <= Grafo>NumVertices ; u++)

p r i n t f ( "Caminho: v[%d ] v[%ld ] d[%d] " , v , Antecessor[ v ] , P[ v ] ) ;

{ /Constroi o heap com todos os valores igual a INFINITO/


Antecessor[u] = 1; P[u] = INFINITO ;

scanf( "%[^\n] " ) ; getchar ( ) ;

A[u+1].Chave = u ;

}
}

/Heap a ser construido/

Itensheap [u] = TRUE ; Pos[u] = u + 1;

}
}

118

Porque o Algoritmo de Dijkstra Funciona

Um hipergrafo ou rgrafo um grafo no direcionado Gr = (V, A) no


qual cada aresta a A conecta r vrtices, sendo r a ordem do
hipergrafo.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.9

}
n = Grafo>NumVertices;
P[(Raiz) ] = 0 ;
Constroi(A, P, Pos) ;

116

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.10.1

123

Implementao por Matrizes de Incidncia


A matriz de incidncia de Gr = (V, A) contendo
n vrtices e m arestas uma matriz n m de
bits, em que A[i, j] = 1 se o vrtice i participar
da aresta j.
Para hipergrafos ponderados, A[i, j] contm o
rtulo ou peso associado aresta e a matriz
no de bits.
Se o vrtice i no participar da aresta j, ento
necessrio utilizar um valor que no possa
ser usado como rtulo ou peso, tal como 0 ou
branco.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.10

122

O Tipo Abstrato de Dados Hipergrafo: Operaes


A forma mais adequada para representar um hipergrafo por meio de
estruturas de dados em que para cada vrtice v do grafo mantida
uma lista das arestas que incidem sobre o vrtice v, o que implica a
representao explcita de cada aresta do hipergrafo.

0 1 2
9
0
1 7 8
9
2 7
8
3
4 7
8 9
5

Essa uma estrutura orientada a arestas e no a vrtices como as


representaes apresentadas at agora.
Existem duas representaes usuais para hipergrafos: as matrizes de
incidncia e as listas de incidncia.

A figura ilustra a representao por matrizes de


incidncia para o hipergrafo do slide 119.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.10

O Tipo Abstrato de Dados Hipergrafo: Operaes


Uma operao que aparece com frequncia a de obter a lista de
arestas incidentes em determinado vrtice.
Para implementar esse operador de forma independente da
representao escolhida para a aplicao em pauta, precisamos de
trs operaes sobre hipergrafos, a saber:
1. Verificar se a lista de arestas incidentes em um vrtice v est vazia.
A operao retorna true se a lista estiver vazia, seno retorna false.
2. Obter a primeira aresta incidente a um vrtice v, caso exista.
3. Obter a prxima aresta incidente a um vrtice v, caso exista.

121

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.10

O Tipo Abstrato de Dados Hipergrafo: Operaes


1. Criar um hipergrafo vazio. A operao retorna um hipergrafo contendo
|V | vrtices e nenhuma aresta.
2. Inserir uma aresta no hipergrafo. Recebe a aresta (V1 , V2 , . . . , Vr ) e seu
peso para serem inseridos no hipergrafo.
3. Verificar se existe determinada aresta no hipergrafo: retorna true se a
aresta (V1 , V2 , . . . , Vr ) estiver presente, seno retorna false.
4. Obter a lista de arestas incidentes em determinado vrtice. Essa
operao ser tratada separadamente logo a seguir.
5. Retirar uma aresta do hipergrafo. Retira a aresta (V1 , V2 , . . . , Vr ) do
hipergrafo e a retorna.
6. Imprimir um hipergrafo.
7. Obter a aresta de menor peso de um hipergrafo. A operao retira a
aresta de menor peso dentre as arestas do hipergrafo e a retorna.

120

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.10.1

127

Implementao por Matrizes de Incidncia

No campo Mat os itens so armazenados em um array de duas


dimenses de tamanho suficiente para armazenar o grafo.

TipoValorAresta NumAresta,
TipoGrafo Grafo)
Tipor v = 0;

As constantes MaxNumVertices e MaxNumArestas definem o maior


nmero de vrtices e de arestas que o grafo pode ter e r define o
nmero de vrtices de cada aresta.

while ( v < Grafo>r && Aux == TRUE)


{ i f ( Grafo>Mat[( Vertices ) [ v ] ] [NumAresta]<=0) Aux = FALSE ;
v = v + 1;
}

Uma possvel implementao para as primeiras seis operaes


definidas anteriormente mostrada no slide a seguir.

return Aux;
}

O procedimento ArestasIguais permite a comparao de duas arestas,


a um custo O(r).

void FGVazio ( TipoGrafo Grafo)


{ int i , j ;
Grafo>ProxDisponivel = 0;

O procedimento InsereAresta tem custo O(r) e os procedimentos


ExisteAresta e RetiraAresta tm custo r |A|, o que pode ser
considerado O(|A|) porque r geralmente uma constante pequena.

for ( i = 0; i < Grafo>NumVertices ; i ++)


for ( j = 0; j < Grafo>NumArestas; j ++) Grafo>Mat[ i ] [ j ] = 0;
}

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.10.1

Implementao por Matrizes de Incidncia


#define MAXNUMVERTICES 100
#define MAXNUMARESTAS 4500
#define MAXR 5
typedef int TipoValorVertice ;
typedef int TipoValorAresta ;
typedef int Tipor ;
typedef int TipoPesoAresta;
typedef TipoValorVertice TipoArranjoVertices [ MAXR ] ;
typedef struct TipoAresta {
TipoArranjoVertices Vertices ;
TipoPesoAresta Peso;
} TipoAresta ;
typedef struct TipoGrafo {
TipoPesoAresta Mat[ MAXNUMVERTICES ] [ MAXNUMARESTAS ] ;
TipoValorVertice NumVertices;
TipoValorAresta NumArestas;
TipoValorAresta ProxDisponivel ;
Tipor r ;
} TipoGrafo ;

126

Implementao por Matrizes de Incidncia

short ArestasIguais ( TipoArranjoVertices Vertices ,

{ short Aux = TRUE ;

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.10.1

125

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.10.1

Implementao por Matrizes de Incidncia


A representao por matrizes de incidncia demanda muita memria
para hipergrafos densos, em que |A| prximo de |V |2 .
Nessa representao, o tempo necessrio para acessar um elemento
independente de |V | ou |A|.
Logo, essa representao muito til para algoritmos em que
necessitamos saber com rapidez se um vrtice participa de
determinada aresta.
A maior desvantagem que a matriz necessita (|V |3 ) de espao.
Isso significa que simplesmente ler ou examinar a matriz tem
complexidade de tempo O(|V |3 ).

124

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.10.1

131

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.10.1

Implementao por Matrizes de Incidncia

Implementao por Matrizes de Incidncia

TipoApontador PrimeiroListaInc ( TipoValorVertice Vertice , TipoGrafo Grafo)

void ImprimeGrafo ( TipoGrafo Grafo)

{ TipoApontador ArestaAtual = 0;

{ int i , j ; p r i n t f ( "

short Continua = TRUE ; TipoApontador Resultado = 0;

130

" );

for ( i = 0; i < Grafo>NumArestas; i ++) p r i n t f ( "%3d" , i ) ;

while ( ArestaAtual < Grafo>NumArestas && Continua == TRUE)

p r i n t f ( " \n" ) ;

{ i f ( Grafo>Mat[ Vertice ] [ ArestaAtual ] > 0 ) { Resultado = ArestaAtual ; Continua = FALSE ; }

for ( i = 0; i < Grafo>NumVertices ; i ++)

else ArestaAtual = ArestaAtual + 1;

{ p r i n t f ( "%3d" , i ) ;

for ( j = 0; j < Grafo>NumArestas; j ++)

i f ( ArestaAtual == Grafo>NumArestas) p r i n t f ( "Erro : Lista incidencia vazia \n" ) ;

p r i n t f ( "%3d" , Grafo>Mat[ i ] [ j ] ) ;

return Resultado;

p r i n t f ( " \n" ) ;

void ProxArestaInc ( TipoValorVertice Vertice , TipoGrafo Grafo,

TipoValorAresta Inc , TipoPesoAresta Peso,

short ListaIncVazia ( TipoValorVertice Vertice , TipoGrafo Grafo)

TipoApontador Prox , short FimListaAdj)

{ short ListaVazia = TRUE ; TipoApontador ArestaAtual = 0;

{ Inc = Prox;

while ( ArestaAtual < Grafo>NumArestas && ListaVazia == TRUE)

Peso = Grafo>Mat[ Vertice ] [ Prox ] ;

{ i f ( Grafo>Mat[Vertice ] [ ArestaAtual ] > 0) ListaVazia = FALSE ;

Prox = Prox + 1;

else ArestaAtual = ArestaAtual + 1;

while (Prox < Grafo>NumArestas && Grafo>Mat[ Vertice ] [ Prox] == 0) Prox = Prox + 1;

FimListaAdj = (Prox == Grafo>NumArestas) ;

return ListaVazia ;

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.10.1

129

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.10.1

Implementao por Matrizes de Incidncia

Implementao por Matrizes de Incidncia

TipoAresta RetiraAresta ( TipoAresta Aresta , TipoGrafo Grafo)

void InsereAresta ( TipoAresta Aresta , TipoGrafo Grafo)

{ TipoValorAresta ArestaAtual = 0;

{ int i ;
i f ( Grafo>ProxDisponivel == MAXNUMARESTAS)

int i ; short EncontrouAresta = FALSE ;

p r i n t f ( "Nao ha espaco disponivel para a aresta \n" ) ;

while ( ArestaAtual<Grafo>NumArestas& EncontrouAresta == FALSE)

else

{ i f ( ArestasIguais(&(Aresta>Vertices ) , ArestaAtual , Grafo) )

{ for ( i = 0; i < Grafo>r ; i ++)

{ EncontrouAresta = TRUE ;

Grafo>Mat[ Aresta>Vertices [ i ] ] [ Grafo>ProxDisponivel]=Aresta>Peso;

Aresta>Peso = Grafo>Mat[ Aresta>Vertices [ 0 ] ] [ ArestaAtual ] ;

Grafo>ProxDisponivel = Grafo>ProxDisponivel + 1;
}

for ( i = 0; i < Grafo>r ; i ++)


Grafo>Mat[ Aresta>Vertices [ i ] ] [ ArestaAtual] = 1;
}
ArestaAtual = ArestaAtual + 1;

}
short ExisteAresta ( TipoAresta Aresta , TipoGrafo Grafo)
{ TipoValorAresta ArestaAtual = 0;
short EncontrouAresta = FALSE ;

while ( ArestaAtual < Grafo>NumArestas &&

return Aresta ;

EncontrouAresta == FALSE)

{ EncontrouAresta =
ArestasIguais(&(Aresta>Vertices ) , ArestaAtual , Grafo ) ;
ArestaAtual = ArestaAtual + 1;
}
return EncontrouAresta;
}

128

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.10.2

135

Implementao por Listas de Incidncia Usando Arranjos

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.10.2

134

Implementao por Listas de Incidncia Usando Arranjos

Os valores armazenados em Prim e Prox so obtidos pela equao


i = a + j|A|, 0 j r 1, e a um ndice de uma aresta no arranjo
Arestas. As entradas de Prim so iniciadas com 1.

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.

Ao inserir a aresta a = 0 contendo os vrtices (1, 2, 4), temos que:


i = 0 + 0 3 = 0, Prox [i = 0] = Prim[1] = 1 e Prim[1] = i = 0,
i = 0 + 1 3 = 3, Prox [i = 3] = Prim[2] = 1 e Prim[2] = i = 3,
i = 0 + 2 3 = 6, Prox [i = 6] = Prim[4] = 1 e Prim[4] = i = 6.

Assim, 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 finalizar a lista.

Ao inserir a aresta a = 1 contendo os vrtices (1, 3, 5) temos que:


i = 1 + 0 3 = 1, Prox [i = 1] = Prim[1] = 0 e Prim[1] = i = 1,
i = 1 + 1 3 = 4, Prox [i = 4] = Prim[3] = 1 e Prim[3] = i = 4,
i = 1 + 2 3 = 7, Prox [i = 7] = Prim[5] = 1 e Prim[5] = i = 7.

Por exemplo, ao se percorrer a lista das arestas do vrtice 2, os


valores {5, 3} so obtidos, os quais representam as arestas que
contm o vrtice 2 (arestas 2 e 0), ou seja, {5 mod 3 = 2, 3 mod 3 = 0}.

Ao inserir a aresta a = 2 contendo os vrtices (0, 2, 5) temos que:


i = 2 + 0 3 = 2, Prox [i = 2] = Prim[0] = 1 e Prim[0] = i = 2,
i = 2 + 1 3 = 5, Prox [i = 5] = Prim[2] = 3 e Prim[2] = i = 5,
i = 2 + 2 3 = 8, Prox [i = 8] = Prim[5] = 7 e Prim[5] = i = 8.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.10.2

Implementao por Listas de Incidncia Usando Arranjos

133

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.10.2

132

Implementao por Listas de Incidncia Usando Arranjos

As arestas so armazenadas no arranjo Arestas. Em cada posio a


do arranjo so armazenados os r vrtices da aresta a e o seu Peso.

A estrutura de dados usada para representar Gr = (V, A) por meio de


listas de incidncia foi proposta por Ebert (1987).

As listas de arestas incidentes nos vrtices do hipergrafo so


armazenadas nos arranjos Prim e Prox .

A estrutura usa arranjos para armazenar as arestas e as listas de


arestas incidentes a cada vrtice. A parte (a) da figura mostra o
mesmo 3-grafo de 6 vrtices e 3 arestas visto anteriormente e a parte
(b) a sua representao por listas de incidncia.

O elemento Prim[v] define o ponto de entrada para a lista de arestas


incidentes no vrtice v, enquanto Prox [Prim[v]], Prox [Prox [Prim[v]]] e
assim por diante definem as arestas subsequentes que contm v.

Prim deve possuir |V | entradas, uma para cada vrtice.


Prox deve possuir r|A| entradas, pois cada aresta a armazenada na
lista de arestas incidentes a cada um de seus r vrtices.

A complexidade de espao O(|V | + |A|), pois Arestas tem tamanho


O(|A|), P rim tem tamanho O(|V |) e P rox tem tamanho
r |A| = O(|A|), porque r geralmente uma constante pequena.

1
11
00
00
11
00
11
00
11
0
1
00
11
3
0
1
00
11
0
1
0
1
0
1
0
1
5
0
1

h0 (x)

Arestas

h1 (x)

1
0
0 (1, 3, 5, 8)
1

0
1
2
Arestas
|A|=3 (1,2,4) (1,3,5) (0,2,5)

(1, 2, 4, 7)

(0, 2, 5, 9)

h2 (x)

(a)

Prim 0
|V|=3 2

1
1

0 1
Prox
r|A|=3x3=9 1 0

2
5

3
4

4
6

5
8

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

(b)

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.10.2

139

Implementao por Listas de Incidncia Usando Arranjos

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.10.2

138

Implementao por Listas de Incidncia Usando Arranjos


typedef struct TipoGrafo {

Uma possvel implementao para as primeiras seis operaes


definidas anteriormente mostrada no programa a seguir.

TipoArranjoArestas Arestas ;
TipoValorVertice Prim[ MAXNUMARESTAS + 1];

O procedimento ArestasIguais permite a comparao de duas arestas


cujos vrtices podem estar em qualquer ordem (custo O(r2 )).

TipoMaxTamProx Prox[ MAXTAMPROX + 2];

O procedimento InsereAresta insere uma aresta no grafo (custo O(r)).

TipoValorAresta NumArestas;

TipoMaxTamProx ProxDisponivel ;
TipoValorVertice NumVertices;
Tipor r ;

O procedimento ExisteAresta verifica se uma aresta est presente no


grafo (custo equivalente ao grau de cada vrtice da aresta no grafo).

} TipoGrafo ;
typedef int TipoApontador;

O procedimento RetiraAresta primeiro localiza a aresta no grafo, retira


a mesma da lista de arestas incidentes a cada vrtice em Prim e Prox
e marca a aresta como removida no arranjo Arestas. A aresta
marcada no arranjo Arestas no reutilizada, pois no mantemos uma
lista de posies vazias.

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.10.2

Implementao por Listas de Incidncia Usando Arranjos


#define MAXNUMVERTICES 100
#define MAXNUMARESTAS 4500
#define MAXR 5
#define MAXTAMPROX MAXR MAXNUMARESTAS
#define INDEFINIDO 1
typedef int TipoValorVertice ;
typedef int TipoValorAresta ;
typedef int Tipor ;
typedef int TipoMaxTamProx;
typedef int TipoPesoAresta;
typedef TipoValorVertice TipoArranjoVertices [ MAXR + 1];
typedef struct TipoAresta {
TipoArranjoVertices Vertices ;
TipoPesoAresta Peso;
} TipoAresta ;
typedef TipoAresta TipoArranjoArestas [ MAXNUMARESTAS + 1];

137

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.10.2

Implementao por Listas de Incidncia Usando Arranjos


O programa a seguir apresenta a estrutura de dados utilizando listas
de incidncia implementadas por meio de arranjos.
A estrutura de dados contm os trs arranjos necessrios para
representar um hipergrafo, como ilustrado na figura do slide 132:
A varivel r utilizada para armazenar a ordem do hipergrafo.
A varivel NumVertices contm o nmero de vrtices do hipergrafo.
A varivel NumArestas contm o nmero de arestas do hipergrafo.
A varivel ProxDisponivel contm a prxima posio disponvel
para insero de uma nova aresta.

136

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.10.2

143

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.10.2

Implementao por Listas de Incidncia Usando Arranjos

Implementao por Listas de Incidncia Usando Arranjos

TipoAresta RetiraAresta (TipoAresta Aresta , TipoGrafo Grafo)

short ExisteAresta (TipoAresta Aresta ,

{ int Aux, Prev , i ; TipoValorAresta A1; Tipor v ;

142

TipoGrafo Grafo)

for ( v = 0; v < Grafo>r ; v++)

{ Tipor v ;

{ Prev = INDEFINIDO ;

TipoValorAresta A1;

Aux = Grafo>Prim[ Aresta>Vertices [ v ] ] ;

int Aux;

A1 = Aux % Grafo>NumArestas;

short EncontrouAresta ;

while(Aux >= 0 && !ArestasIguais (Aresta>Vertices , &A1, Grafo) )

EncontrouAresta = FALSE ;

{ Prev = Aux;
Aux = Grafo>Prox[Aux] ;

for (v = 0; v < Grafo>r ; v++)

A1 = Aux % Grafo>NumArestas;

{ Aux = Grafo>Prim[ Aresta>Vertices [ v ] ] ;


while (Aux != 1 && !EncontrouAresta)

{ A1 = Aux % Grafo>NumArestas;

i f (Aux >= 0)
{ i f ( Prev == INDEFINIDO ) Grafo>Prim[ Aresta>Vertices [ v ] ] = Grafo>Prox[Aux] ;

i f ( ArestasIguais (Aresta>Vertices , &A1, Grafo) )

else Grafo>Prox[Prev] = Grafo>Prox[Aux] ;

EncontrouAresta = TRUE ;

Aux = Grafo>Prox[Aux] ;

TipoAresta Resultado = Grafo>Arestas [A1] ;

for ( i = 0; i < Grafo>r ; i ++) Grafo>Arestas [A1] . Vertices [ i ] = INDEFINIDO ;

return EncontrouAresta ;

Grafo>Arestas [A1] .Peso = INDEFINIDO ;

return Resultado;
}

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.10.2

141

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.10.2

Implementao por Listas de Incidncia Usando Arranjos

Implementao por Listas de Incidncia Usando Arranjos

void InsereAresta(TipoAresta Aresta , TipoGrafo Grafo)

short ArestasIguais ( TipoArranjoVertices V1,


TipoValorAresta NumAresta, TipoGrafo Grafo)

{ int i , Ind ;
i f ( Grafo>ProxDisponivel == MAXNUMARESTAS + 1)

{ Tipor i = 0 , j ;

p r i n t f ( "Nao ha espaco disponivel para a aresta \n" ) ;

short Aux = TRUE ;

else

while ( i < Grafo>r && Aux)

{ Grafo>Arestas [Grafo>ProxDisponivel ] = Aresta ;

{ j = 0;
while ( (V1[ i ] ! = Grafo>Arestas[NumAresta] . Vertices [ j ]) &&

for ( i = 0; i < Grafo>r ; i ++)

( j < Grafo>r ) ) j ++;

{ Ind = Grafo>ProxDisponivel + i Grafo>NumArestas;

i f ( j == Grafo>r ) Aux = FALSE ;

Grafo>Prox[ Ind ] =

i ++;

Grafo>Prim[Grafo>Arestas [Grafo>ProxDisponivel ] . Vertices [ i ] ] ;


}

Grafo>Prim[Grafo>Arestas [Grafo>ProxDisponivel ] . Vertices [ i ]]= Ind ;


}
}
Grafo>ProxDisponivel++;
}

return Aux;
}
void FGVazio(TipoGrafo Grafo)
{ int i ;
Grafo>ProxDisponivel = 0;
for ( i = 0; i < Grafo>NumVertices ; i ++) Grafo>Prim[ i ] = 1;
}

140

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.10.2

147

Programa Teste para Operadores do Tipo Abstrato de


Dados Hipergrafo

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.10.2

Programa Teste para Operadores do Tipo Abstrato de


Dados Hipergrafo

for ( i = 0; i < Grafo.NumArestas; i ++)

/ Entram aqui tipos do Slide 125 ou do Slide 137 /

{ p r i n t f ( "Insere Aresta e Peso: " ) ;

/ Entram aqui operadores do Slide 127 ou do Slide 138 /

for ( j =0; j < Grafo. r ; j ++) scanf( "%d[^\n] ",&Aresta . Vertices [ j ] ) ;

int main( ) {

scanf( "%d[^\n] " , &Aresta .Peso) ;

TipoApontador Ap;

getchar ( ) ;

int i , j ;

InsereAresta (&Aresta, &Grafo ) ;

TipoValorAresta Inc ;

TipoValorVertice V1;

/ / Imprime estrutura de dados

TipoAresta Aresta ;

p r i n t f ( "prim : " ) ; for ( i = 0; i < Grafo.NumVertices ; i ++)

TipoPesoAresta Peso;

p r i n t f ( "%3d" , Grafo.Prim[ i ] ) ; p r i n t f ( " \n" ) ;

TipoGrafo Grafo;

p r i n t f ( "prox : " ) ; for ( i = 0; i < Grafo.NumArestas Grafo. r ; i ++)

short FimListaInc ;

p r i n t f ( "%3d" , Grafo.Prox[ i ] ) ; p r i n t f ( " \n" ) ;

p r i n t f ( "Hipergrafo r : " ) ; scanf( "%d[^\n] " , &Grafo. r ) ;

ImprimeGrafo(&Grafo ) ;

p r i n t f ( "No. vertices : " ) ; scanf( "%d[^\n] " , &Grafo.NumVertices) ;

getchar ( ) ;

p r i n t f ( "No. arestas : " ) ;

p r i n t f ( " Lista arestas incidentes ao vertice : " ) ;

getchar ( ) ;

scanf( "%d[^\n] " , &V1) ;

FGVazio (&Grafo ) ;

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.10.2

145

scanf( "%d[^\n] " , &Grafo.NumArestas) ;

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.10.2

Implementao por Listas de Incidncia Usando Arranjos

Implementao por Listas de Incidncia Usando Arranjos

/ operadores para obter a l i s t a de arestas incidentes a um vertice /

void ImprimeGrafo(TipoGrafo Grafo)

short ListaIncVazia ( TipoValorVertice Vertice ,

{ int i , j ;

TipoGrafo Grafo)

p r i n t f ( " Arestas : Num Aresta , Vertices , Peso \ n" ) ;

{ return Grafo>Prim[ Vertice] == 1; }

for ( i = 0; i < Grafo>NumArestas; i ++)


{ p r i n t f ( "%2d" , i ) ;

TipoApontador PrimeiroListaInc ( TipoValorVertice Vertice ,

for ( j = 0; j < Grafo>r ; j ++) p r i n t f ( "%3d" , Grafo>Arestas [ i ] . Vertices [ j ] ) ;

TipoGrafo Grafo)

p r i n t f ( "%3d\n" , Grafo>Arestas [ i ] .Peso) ;

{ return Grafo>Prim[ Vertice ] ; }

void ProxArestaInc( TipoValorVertice Vertice , TipoGrafo Grafo,

for ( i = 0 ; i < Grafo>NumVertices ; i ++)

p r i n t f ( " Lista arestas incidentes a cada vertice : \ n" ) ;


TipoValorAresta Inc , TipoPesoAresta Peso,
TipoApontador Prox ,

{ p r i n t f ( "%2d" , i ) ;

short FimListaInc )

j = Grafo>Prim[ i ] ;

/ Retorna Inc apontado por Prox /

while ( j ! = INDEFINIDO)

{ Inc = Prox % Grafo>NumArestas;

{ p r i n t f ( "%3d" , j % Grafo>NumArestas) ;

Peso = Grafo>Arestas[Inc ] .Peso;

j = Grafo>Prox[ j ] ;

i f ( Grafo>Prox[Prox] == INDEFINIDO)

FimListaInc = TRUE ;

p r i n t f ( " \n" ) ;

else Prox = Grafo>Prox[Prox ] ;


}

146

}
}

144

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.10.2

Programa Teste para Operadores do Tipo Abstrato de


Dados Hipergrafo

149

Projeto de Algoritmos Cap.7 Algoritmos em Grafos Seo 7.10.2

Programa Teste para Operadores do Tipo Abstrato de


Dados Hipergrafo
i f ( ! ListaIncVazia(&V1, &Grafo) )

i f ( ExisteAresta(&Aresta, &Grafo) )

{ Ap = PrimeiroListaInc(&V1, &Grafo ) ;

p r i n t f ( "Sim\n" ) ;

FimListaInc = FALSE ;

else p r i n t f ( "Nao\n" ) ;

while ( ! FimListaInc )

p r i n t f ( " Retira aresta : " ) ;

{ ProxArestaInc (&V1, &Grafo, &Inc , &Peso, &Ap, &FimListaInc ) ;

for ( j = 0; j < Grafo. r ; j ++) scanf( "%d[^\n] " , &Aresta . Vertices [ j ] ) ;

p r i n t f ( "%2d (%d) " , Inc % Grafo.NumArestas, Peso) ;

getchar ( ) ;

i f ( ExisteAresta(&Aresta, &Grafo) )
{ Aresta = RetiraAresta(&Aresta, &Grafo ) ;
p r i n t f ( "Aresta retirada : " ) ;
for ( i = 0; i < Grafo. r ; i ++) p r i n t f ( "%3d" , Aresta . Vertices [ i ] ) ;
p r i n t f ( "%4d\n" , Aresta .Peso) ;
}
else p r i n t f ( "Aresta nao existe \n" ) ;
ImprimeGrafo(&Grafo ) ;
return 0;
}

p r i n t f ( " \n" ) ; getchar ( ) ;


}
else p r i n t f ( " Lista vazia \n" ) ;
p r i n t f ( "Existe aresta : " ) ;
for ( j = 0; j < Grafo. r ; j ++) scanf( "%d[^\n] " , &Aresta . Vertices [ j ] ) ;
getchar ( ) ;

148

You might also like