Vous êtes sur la page 1sur 11

Ministério da Educação

PR
UNIVERSIDADE TECNOLÓGICA FEDERAL DO PARANÁ
Universidade Tecnológica Federal do Paraná
Pró-Reitoria de Pesquisa e Pós-Graduação

Relatório Final de Atividades

Algoritmo de Malgrange
vinculado ao projeto
Teoria dos Grafos

Cristiano Gonçalves de Araujo


Voluntário
Engenharia Ambiental
Data de ingresso no programa: 06/2013
Prof(ª). Msc. Fausto Pinheiro Silva

Área do Conhecimento:
1.03.03.01-4 Linguagens de Programação

CAMPUS Medianeira, 2014


CRISTIANO GONÇALVES DE ARAUJO
FAUSTO PINHEIRO SILVA

ALGORITMO DE MALGRANGE

Relatório Pesquisa do Programa de


Iniciação Científica ou Programa de
Iniciação Tecnológica da Universidade
Tecnológica Federal do Paraná.

MEDIANEIRA, 2014
SUMÁRIO

INTRODUÇÃO 4
MATERIAIS E MÉTODOS 4
RESULTADOS E DISCUSSÕES 8
CONCLUSÕES 10
REFERÊNCIAS 10
INTRODUÇÃO

Uma das grandes necessidades atualmente é determinar algoritmos eficientes para


encontrar rotas em grafos orientados. O algoritmo de Malgrange determina as componentes
f-conexas de um grafo orientado. Conseqüentemente, se dois vértices a, b pertencem a uma
mesma componente f-conexa então existem um caminho de a para b e um caminho de b
para a.
A modelagem de um problema de minimizar e determinar rotas de entrega se torna
mais fácil em um grafo f-conexo ou a região de entrega é uma componente f-conexa. Se
um grafo que modela este problema não for f-conexo, haverá rua onde o entregador quando
entrar nela não poderá sair. A determinação das componentes f-conexas de um grafo
orientado é uma etapa muito importante no estudo de muitos modelos de grafos, visto que
ela permite que se façam estudos locais mais detalhados. Para facilitar o determinação da
componentes f-conexas vamos implementar o algoritmo de Malgrange.

Fundamentação Teórica

Como representar um grafo

Existem muitas formas de se organizar os dados sobre de grafo, de modo que eles
possam ser introduzidos em um computador. A mais intuitiva delas consiste em dizer, para
cada vértice, quais outros vértices estão ligados a ele (ou adjacentes a ele). Isto pode ser
ilustrado na figura 1 e 2.

Figura 1 – Grafo não Orientado Figura 2 – Grafo Orientado

Fonte: Grafos: introdução e prática, 2009


Fonte: Grafos: introdução e prática, 2009

A matriz de adjacência

Podemos tomar os rótulos dos vértices e associá-los às linhas, e também às colunas,


de uma matriz quadrada (matriz de adjacência). Vamos exemplificar com os grafos das
figura 1 e 2 a matriz de adjacência. Para o grafo orientado imagine que os arcos tenham um
peso.

Figura 3 – Matriz de Adjacência Figura 4 – M. A. de um grafo orientado

Fonte: Grafos: introdução e prática, 2009

Fonte: Grafos: introdução e prática, 2009

Vizinhança

Ao discutir a representação de grafos, falamos de relações de adjacência. Essa noção


nos leva à idéia de vizinhança, ou seja, o que está mais próximo (no caso, de um vértice do
grafo).
Então diremos que, em um grafo G = (V, E) não orientado, um vértice y é vizinho de
um vértice x se existir em G uma aresta (x,y). E a vizinhança, ou vizinhança aberta de x,
que denotamos N( x ), é o conjunto de vértices de G que sejam vizinhos de x:
N( x ) = { y | (x,y) é aresta em G } .
Da mesma forma, poderemos definir a vizinhança N( W ) de um conjunto W de
vértices. Aqui é importante dizer que os vértices da vizinhança devem ser externos a W, o
que fica implícito ao se lidar com um só vértice.
Em um grafo G = ( V, E ) orientado, os vizinhos de um vértice x se subdividem em
sucessores e antecessores, conforme se esteja seguindo um arco de x para um seu vizinho,
ou o contrário. A notação é semelhante, apenas se designa a saída por um sobrescrito ( + ) e
a entrada por um ( - ).

Sucessores: ( x ) = { y | ( x, y) é aresta em G};


Antecessores: ( x ) = { y | ( y, x) é aresta em G}.

Observe as figuras a seguir.


Figura 5 – Vizinhanças de um Grafo não Figura 6 – Vizinhanças de Grafo orientado.
Orientado.

Fonte: Grafos: introdução e prática.


Fonte: Grafos: introdução e prática.
Em uma abordagem com algoritmos, às vezes se usa a vizinhança fechada,
denotada por N[ x ], que inclui o vértice no qual ela se baseia. Não há, é claro, maior
dificuldade em se passar de uma noção à outra, basta notar que N[x] = N(x) {x}.

Fecho transitivo

Em um grafo, se existe a ligação (v,w), diremos que w é atingível a partir de v.


Então poderemos pensar em usar outra ligação para ir adiante: esta relação de
atingibilidade é transitiva, pois se houver uma ligação ( w,x ) poderemos chegar a x e
este será também atingível de v.
Mais ainda, poderemos procurar todos os vértices atingíveis em um grafo G não
orientado a partir de v dado: este conjunto é chamado fecho transitivo de v em G. Ele é
designado por R( v ).
Se estivermos em um grafo orientado, haverá dois desses fechos:
 o fecho transitivo direto, que procura ( iterativamente ) sucessores de
vértices e é o conjunto de todos os vértices atingíveis a partir de v. Estes
vértices são chamados os descendentes de v.
 o fecho transitivo inverso, que procura ( iterativamente ) antecessores de
vértices e é o conjunto de todos os vértices a partir dos quais v é atingível.
Estes vértices são chamados os ascendentes de v.

Para um vértice v, designaremos esses fechos, por ( v ) e ( v ),


respectivamente. É importante observar que um fecho transitivo sempre inclui o seu
vértice origem, por coerência: ele é, naturalmente, atingível de si mesmo.
A figura a seguir mostra exemplos destes dois últimos fechos.
Figura 7 – Fecho Transitivo

Fonte: Grafos: introdução e prática, 2009

Observe com cuidado atingibilidade em cada caso. Note que os conjuntos


referenciados na figura são de vértices.

Conexidade

Na teoria de grafos existem alguns tipos de conexidades. Neste trabalho vamos


considerar um caso em que o grafo é fortemente conexo.

Grafo fortemente conexo (f-conexo): Para todo par de vértices u e v existe um


caminho de u até v e existe um caminho de v até u.

Figura 8 - Grafo fortemente conexo

Fonte: Grafos: introdução e prática, 2009


Dentro de qualquer grafo orientado, poderemos identificar subgrafos f-conexos que
sejam maximais (ou seja, que não façam parte de outros que sejam também f-conexos).
Um subgrafo maximal f-conexo é chamado uma componente f-conexa.

Algoritmo de Malgrange

Vamos usar um conjunto provisório W para guardar os descendentes de um


vértice v. Este conjunto vai permitir um teste de parada, que é W { )}:
enquanto a igualdade não se verificar, haverá vértices para adicionar em R (aqui o (*)
significa (+) na primeira passada e (-) na segunda).

No algoritmo, a seta () significa “recebe”, ou seja, estamos atribuindo ao


primeiro membro o valor do segundo. Observe que os sinais “igual” e “diferente” são
usados nos testes.

Entrada: Grafo G = (V, E)


Y  V ( Y armazena os vértices ainda não pertencentes a uma componente)
I  0 ( I indexa as componentes conexas encontradas)
enquanto X fazer
I  I + 1;
 ;( armazena os descendentes do vértice em questão)
 ;( armazena os ascendentes do vértice em questão)
escolher v Y;
W ;  {v};
enquanto W { )} fazer
 { )};
fim-fazer
W ;  {v};
enquanto W { )} fazer
 { )};
fim-fazer
componente ( I )  ;
Y  Y – componente (I);
fim-fazer.

Resultados e Discussões

O Grafo.java é uma classe que gera um objeto do tipo grafo. Seu método
construtor obrigatoriamente recebe um inteiro n como parâmetro, para que seja criada
uma matriz de ordem nxn com seus respectivos valores zerados. A classe grafo além de
seus sets e gets, possui outros métodos importantes tais como: o método insereAresta
quer faz a inserção das arestas entre os vértices e o método existeAresta que retorna
verdadeiro caso exista aresta entre os vértices indicados por parâmetro.

Figura 9 - Grafo.java

Fonte: Projeto de Algoritmos com implementação em Java e , 2006

A classe Malgrange é uma classe que utiliza o algoritmo de Malgrange para


retornar as componentes f-conexas de um grafo. Por definição essa classe recebe por
parâmetro um grafo (definido acima). Classe possui o método conectividade que usando
a ideia de busca em profundidade encontra e faz uma interseção entre vizinhança
sucessora e antecessora de cada vértice do grafo, e posteriormente faz a comparação
entre eles para encontrar seus equivalentes. Ao final a classe retorna uma string
mostrando suas componentes conexas.

Figura 10 - Malgrange.java

Fonte: Própria, 2014

Vamos ilustrar com um exemplo, para isto considere o grafo da figura 11.

Figura 11 – Exemplo de implementação do algoritmo de Magrange

Fonte: Grafos: introdução e prática, 2009

A classe UsaGrafo.java como o próprio nome diz, é uma classe que contém a função
main() onde de fato será usado as classes Grafo e Malgrange. Nela existe a interação
com o usuário que poderá adicionar arestas ao grafo. No final será apresentado na tela
as componente f-conexas junto com a matriz de adjacência do exemplo ilustrado na
figura 11.
Figura 12 – UsaGrafo.java

Fonte: Própria, 2009


Considerações Finais.

A implementação do algoritmo nos permite determinar facilmente se existe


ligação entre dois vertice ou não em um grafo orientado. No trânsito, por exemplo, é
claro que o grafo que modela a rede de ruas terá de ser f-conexo ou, então, haverá
alguma rua onde um carro não poderá entrar, ou, se entrar, não mais poderá sair. Um
percurso fechado que utilize todas as arestas de um grafo, uma vez e uma só, é chamado
um percurso euleriano; um grafo que possua tal percurso é chamado grafo euleriano.
Todo grafo euleriano é fortemente conexo, mas um grafo fortemente conexo nem
sempre é euleriano. Isto pode ser visto na figura 11.
A união de componentes fortemente conexa não é uma componente f-conexa. Isto
pode ser observado na figura 11. A determinação das componentes f-conexas de um
grafo orientado é uma etapa muito importante no estudo de muitos modelos de grafo,
porque ela permite que se façam estudos locais mais detalhados. (Pense em um modelo
no qual o grafo tenha, por exemplo, 50.000 vértices!).

REFERÊNCIAS

[1] BIGGS, N. Algebraic Graph Theory, New York: Cambridge University Press,
1974.
[2] BOLLOBÁS, B. Graph Theory: an Introductory Course, North Holland:
Springer-Verlag, 1979.
[3] BOAVENTURA NETTO, P. O; JURKIEWICZ, S. Grafos: introdução e prática,
São Paulo: Editora Blucher, 2009.
[4] COUTINHO, S. C. Números Inteiros e Criptografia RSA. Rio de Janeiro:
Instituto Nacional de Matemática Pura e Aplicada – IMPA; 1997.
[5] FEOFILOFF, P.; KOHAYAKAWA, Y .; WAKABAYASHI, Y, Uma Introdução
Sucinta à Teoria dos Grafos, 2004.
[6] REINHARD, D. Graph Theory, New York, Springer, 2000.
[7] ZIVIANI, N. Projeto de Algoritmos com implementação em Java e ++ , São
Paulo: Cengage Learning, 2006.

Vous aimerez peut-être aussi