Aula 12: Algoritmos de Grafos
24/02/2003
Também disponível nos formatos pdf e no formato ps.
Neste capítulo vamos discutir alguns problemas comuns da teoria dos grafos. Muitos dos problemas da teoria dos grafos podem ser utilizados na prática.
Exemplo:
Um exemplo de uma situação real que pode ser modelada por um grafo é o sistema de aeroportos.
Existem duas formas de representar um grafo :
A representação com listas de adjacência é mais utilizada poque provê
uma forma compacta de representar grafos esparsos , isto é, grafos
onde é bem menos do que
.
A representação com matriz de adjacência é indicada no caso de grafos
densos, onde é perto de
.
A representação com listas de adjacência de um grafo consiste de um
array
de
listas, um para cada vértice de
. Para cada
,
a lista de adjacência
contém um ponteiro para todos os vértices
,
onde existe um arco
. Logo,
consiste de todos os vértices
de
que são adjacentes a
. Esses vértices são armazenados em ordem
arbitrária.
A figura abaixo mostra um grafo não dirigido e sua representação com listas de adjacência.
Se é um grafo dirigido, a soma dos tamanhos de todas as listas de
adjacências é
. A figura abaixo mostra um grafo dirigido e sua representação
com listas de adjacência.
Em ambos os casos, grafos dirigidos ou não, a representação com listas de
adjacÊncia possui uma propriedade desejável que indica que a quantidade de
memória requerida é
.
As listas de adjacência também pode ser utilizadas no caso de grafos ponderados e outras variantes de grafos.
A maior desvantagem desse método de representação é a de não possuir uma
forma eficiente de dizer se um determinado arco está presente no
grafo.
A representação por matriz de adjacência de um grafo requer
que os vértices sejam arbitrariamente numerados de
. A matriz
de adjacência de um grafo de uma matriz
, de ordem
, onde
A figura abaixo mostra um grafo não dirigido e sua representação com matriz de
adjacência. Esse tipo de representação requer de memória,
independentemente do número de arcos do grafo.
Da mesma forma, a matriz de adjacência pode ser usada para representar grafos dirigidos.
Como na representação com listas de adjacência, a matriz de adjacência pode
ser usada para representar grafos ponderados. Em vez de usar para indicar a
presença do arco, utiliza-se o peso do arco.
Embora a representação com lista de adjacência seja pelo menos tão eficiente quanto a representação com matriz de adjacência, a simplicidade de uma matriz de adjacência a torna preferível no caso de grafos pequenos. No caso de grafos não ponderados, a representação com matriz de adjacência tem a vantagem de requerer apenas um bit por entrada.
Existem dois tipos principais de pesquisa (caminhamento) em grafos:
A busca em amplitude representa um dos mais simples algoritmos de busca em grafo. Apesar de sua simplicidade, esse método funciona como modelo para vários importantes algoritmos de grafos como, por exemplo, o algoritmode caminho mais curto de Dijkstra e o algoritmo da árvore mínima de cobertura de Prim.
Se um grafo e um vértice inicial
. A busca em amplitude processa
os vértices por níveis, começando pelos vértices mais proóximos do vértice inicial
e deixando os vértices mais distantes para depois. Esse tipo de busca
é bastante similar ao caminhamento por níveis em árvores.
O algoritmo de busca em amplitude pode ser resumido nos seguintes passos e funciona tanto para grafos dirigidos ou não:
O algoritmo, portanto, descobre todos os vértices com distância a partir de
antes de descobrir os vértics com distância
.
Para manter controle do processamento dos vértices no algoritmo, é necessário marcar os vértices. Utilizamos um sistema de 3 cores: branca, azul e vermelha.
Como dito anteriormente, a busca em amplitude constroi uma árvore de amplitude,
inicialmente contendo apenas a raiz que é o nó de origem. Sempre que um vértice branco
é descoberto a partir de um vértice já descoberto
, ele é adicionado
à árvore, juntamente com o arco
. O vértice
é o predecessor de
na árvore. Como cada vértice só é descoberto uma única vez, ele possui apenas um
predecessor.
O algoritmo BFS abaixo corresponde ao algoritmo de busca por amplitude e
assume que o grafo é representado com listas de adjacência.
Para cada vértice no grafo, o algoritmo mantém estruturas auxiliares:
Exemplo
O exemplo abaixo mostra a utilização do algoritmo BFS em um grafo não dirigido.
A busca em profundidade é uma generalização do caminhamento em pré-ordem.
Como o próprio nome indica, a idéia principal é buscar verticalmente
sempre que possível. Nesta estratégia, sempre que um novo vértice é
descoberto, ele deve ser explorado por completo. Quando não existe mais
nenhum vértice a ser explorado, efetua-se um bactrack para o vértice que
propiciou a descoberta de
.
Alguns detalhes do algoritmo de busca em profundidade:
Exemplo
O exemplo a seguir, mostra o progresso da execução do algoritmo DFS sobre um grafo dirigido.
O algoritmo de busca em profundidade pode ser facilmente modificado para
classificar os tipos de arcos do grafo . Podemos distinguir 4 tipos de
arcos:
Essa classificação pode servir para indicar certos aspectos do grafo. Por exemplo, podemos afirmar que um grafo é acíclico se ele não possuir arcos de retorno.
A ordenação topológica pode ser vista como uma aplicação da técnica de busca em profundidade, que consiste em ordenar o conjunto de vértices de um grafo acíclico dirigido.
Podemos definir uma ordenação topológica de um grafo acíclico dirigido
como uma ordenação linear de todos os vértices que satisfaz
a seguinte condição:
Secontém um arco
, então
aparece antes de
na ordenação.
O seguinte algoritmo ordena topologicamente um grafo acíclico dirigido.
Esse algoritmo é pois, o algoritmo DFS é
e a
inserção na lista encadeada é
.
Exemplo
Grafos acíclicos dirigidos são usados em muitas aplicações para indicar precedência entre eventos. Por exemplo, a estrutura de pré-requisitos das disciplinas do Curso de Ciência da Computação na UFPB.
A ordenação topológica das disciplinas seria qualquer seqüência de disciplinas que não violasse a estrutura de pré-requisitos.
Para ilustrar a aplicação apresentada, vamos considerar a figura a seguir. Ela apresenta uma estrutura de pré-requisitos entre 9 disciplinas de um determinado curso. O tempo de inicial e final dos vértices, obtidos através do algoritmo de busca em profundidade estão também indicados.
Uma possível solução para a ordenação topológica do grafo está mostrada a seguir.