12 GrafosB
12 GrafosB
LEEC
Teoria de Grafos e Algoritmos em Grafos – 2ª Parte
Grafos – DFS
Notar que a estratégia de procura de Tremaux, mais não é que
procura em profundidade primeiro.
O algoritmo procede sempre abrindo uma porta e afastando-
se da origem, até que chega a um ponto em que não pode
abrir mais portas, tendo então que recuar até ao último ponto
onde deixou, pelo menos, uma porta por abrir.
Se ao recuar nunca encontrar portas por abrir, acabará
regressando ao ponto de partida, dado que o fio que
desenrolou no caminho descendente, lhe permite esse
regresso.
62 AED (IST/DEEC)
Grafos – Implementação de DFS
(matriz de adjacências)
63 AED (IST/DEEC)
Grafos – Descrição da Implementação
A tabela pre está associada com as lâmpadas. Se pre[i]
valer –1, significa que a luz está apagada para esse vértice.
Quando se encontra uma aresta para um vértice em que pre
não vale –1, um vértice já visitado, essa aresta não é seguida.
Finalmente, a própria estrutura da recursão estabelece o
mecanismo equivalente a desenrolar o novelo de fio.
Quando um vértice não possui mais vértices adjacentes com
pre igual a –1, a chamada recursiva termina, devolvendo o
controlo de execução para o vértice que o antecedeu na
recursão.
O retorno da recursão é equivalente a voltar a enrolar o fio.
64 AED (IST/DEEC)
Grafos – Implementação de DFS
(lista de adjacências)
65 AED (IST/DEEC)
Grafos – Comparação
Na implementação por matriz de adjacências, para cada vértice
examinam-se todos as arestas que lhe são incidentes por
ordem de numeração dos vértices de saída.
Avança sempre pelo primeiro (de índex mais baixo) que não tenha sido
visitado e lhe é adjacente.
Na implementação por listas de adjacências, são
imediatamente considerados os vértices adjacentes e a ordem
de inspecção pode não coincidir com a numeração.
Avança sempre pelo primeiro da lista de adjacências que não tenha sido
ainda visitado.
66 AED (IST/DEEC)
Grafos – ADT para procura
static int cnt, pre[maxV]; GRAPHsearch é uma função ADT
para procura genérica em grafos,
void GRAPHsearch(Graph *G) realizando os seguintes passos:
{
int v; Encontra um vértice não
cnt = 0; marcado.
for (v = 0; v < G->V; v++)
pre[v] = -1; Visita (e marca como
for (v = 0; v < G->V; v++) visitados) todos os vértices
if (pre[v] == -1) no sub-grafo ligado a que o
search(G, EDGE(v, v)); primeiro vértice pertence.
}
67 AED (IST/DEEC)
Grafos – Propriedades da procura
Propriedade – Uma função de procura em grafos marca cada
vértice do grafo se e só se a função de procura que usa
marcar cada vértice do sub-grafo ligado que contiver o vértice
inicial.
Demonstração trivial por indução no número de sub-grafos ligados
máximos.
Propriedade – A DFS num grafo representado por matriz de
adjacências requer um tempo proporcional a 𝑉2.
Cada entrada da matriz de adjacências é inspeccionada uma só vez.
Propriedade – A DFS num grafo representado por listas de
adjacências requer um tempo proporcional a 𝑉 + 𝐸.
Inicialização proporcional a V, após o que se fazem V chamadas
recursivas e cada elemento das listas de adjacências é inspeccionado
uma só vez.
68 AED (IST/DEEC)
Grafos – Tabelas indexadas por vértices
Muitas funções sobre grafos requerem a existência, o uso ou
construção de tabelas indexadas pelos vértices dos grafos que
processam.
Tais tabelas são incluídas em vários níveis de abstracção
Como variáveis globais – ex: pre em DFS.
Na representação do próprio grafo – ex: grau de um vértice
Como parâmetros passados, fornecidos pelos próprios clientes – ex: ao
calcular alguma tabela que seja função dos vértices.
A inicialização destas tabelas é tipicamente feita colocando
todas as entradas a –1, por forma a poderem paralelamente
ser usadas com a mesma utilidade da tabela pre, atrás
apresentada.
69 AED (IST/DEEC)
Grafos - BFS
Se o objectivo for encontrar o caminho mais curto entre um
par de vértices, caso exista, a DFS não é muito útil.
A DFS poderá encontrar um caminho, mas não dá garantias de
que seja o mais curto, a menos que se determinem todos
explicitamente para posterior avaliação.
A procura em largura primeiro (“BFS – Breadth First Search”)
é baseada exactamente nesse objectivo.
Quando temos mais que uma aresta para percorrer,
escolhemos uma e guardamos as outras para explorar mais
tarde.
Em DFS usamos uma pilha (LIFO) – avança para longe da entrada
enquanto puder.
Em BFS usamos um fila (FIFO) – só avança para longe da entrada depois
de ter investigado todos corredores que dela saem.
70 AED (IST/DEEC)
Grafos – Implementação de BFS
(matriz de adjacências)
# define bfs search Cria uma fila (FIFO) com todas
void bfs(Graph *G, Edge *e) as arestas incidentes de vértices
{ visitados e de vértices ainda não
int v;
visitados.
QUEUEput(e);
while (!QUEUEempty())
if (pre[(e = QUEUEget())->w] == -1) Toma a primeira aresta da fila até
{ encontrar uma que aponte para
pre[e->w] = cnt++; um vértice não visitado.
st[e->w] = e->v;
for (v = 0; v < G->V; v++) Visita esse vértice, colocando na
if (G->adj[e->w][v] == 1)
fila todas as arestas que apontam
if (pre[v] == -1)
para vértices não visitados.
QUEUEput(EDGE(e->w, v));
}
} Tabela st guarda informação
sobre o vértice antecessor.
71 AED (IST/DEEC)
Grafos – Exemplo de execução (BFS)
72 AED (IST/DEEC)
Grafos – Exemplo de execução (BFS)
0 2
73 AED (IST/DEEC)
Grafos – Exemplo de execução (BFS)
0 2
6
7
74 AED (IST/DEEC)
Grafos – Exemplo de execução (BFS)
0 2
6
7
5 4
75 AED (IST/DEEC)
Grafos – Exemplo de execução (BFS)
0 2
6
1 7
5 4
76 AED (IST/DEEC)
Grafos – Exemplo de execução (BFS)
0 2
6
1 7
5 4
77 AED (IST/DEEC)
Grafos – Exemplo de execução (BFS)
0 2
6
1 7
5 4
78 AED (IST/DEEC)
Grafos – Exemplo de execução (BFS)
0 2
6
1 7
5 4
79 AED (IST/DEEC)
Grafos – Propriedades da BFS (1)
Propriedade – Durante a BFS, os vértices entram e saem da
fila FIFO por ordem crescente da sua distância ao vértice
inicial.
Demonstração – Verifica-se uma propriedade mais forte: a fila
consiste sempre de zero ou mais vértices distando 𝑘 passos
do vértice inicial, seguidos de zero ou mais vértices distando
𝑘 + 1 passos dos vértice inicial, para algum valor de 𝑘.
É fácil provar esta propriedade por indução.
81 AED (IST/DEEC)
Grafos – Propriedades da BFS (2)
Propriedade – A BFS visita todos os vértices e arestas de um
grafo em tempo proporcional a 𝑉2 para a representação por
matriz de adjacências e proporcional a 𝑉 + 𝐸 para a
representação por listas de adjacências.
Demonstração:
Tal como em DFS, a implementação inspecciona completamente a linha
da matriz de adjacências ou a lista de pares adjacentes associada com
cada vértice visitado.
Basta mostrar que todos os vértices são visitados.
Todos os vértices que podem ser alcançados a partir do início estão
(i) Na árvore criada pela procura, (ii) na fila, ou (iii) são alcançáveis a partir
dos vértices que estão na fila.
Todos os vértices se deslocam de (iii) para (ii) e depois para (i), sendo que em
cada iteração do ciclo while (i) aumenta a sua cardinalidade.
82 AED (IST/DEEC)
Grafos – Implementação melhorada de
BFS – (matriz de adjacências)
void bfs(Graph *G, Edge *e)
{
int v, w;
QUEUEput(e);
pre[e->w] = cnt++;
while (!QUEUEempty())
{ Guarda apenas
e = QUEUEget();
w = e->w;
os vértices por
st[w] = e->v; visitar
for (v = 0; v < G->V; v++)
if ((G->adj[w][v] == 1) && (pre[v] == -1))
{
QUEUEput(EDGE(w, v));
pre[v] = cnt++;
}
}
}
83 AED (IST/DEEC)
Grafos – Problemas que BFS resolve
Caminho mais curto entre v e w
Tomar v como o vértice inicial e aplicar BFS até que pre[w] deixe de
ser –1.
Caminhos mais curtos a partir de um vértice fonte
Tomar o vértice fonte como inicial e executar a BFS até ao fim.
Todos os caminhos mais curtos
Como a BFS permite encontrar o caminho mais curto de um vértice
inicial para todos os outros, basta aplicar BFS para cada um dos vértices
do grafo dado como ponto de partida.
A complexidade desta solução é cúbica no número de vértices para
representação por matrizes de adjacências.
84 AED (IST/DEEC)
Grafos – Procura generalizada (1)
Tanto a DFS como a BFS são casos particulares de procura
generalizada em grafos.
A implementação da BFS que se apresentou, introduz a pista
essencial de resolução de qualquer outro mecanismo de
procura.
Isto é, tudo depende da forma como se inserem novos vértices na fila,
assumindo que se retira sempre o vértice que encabeça a fila.
Substitua-se o conceito de fila pelo conceito de “franja”, ou
fronteira.
Todos os vértices que estão na franja são os não visitados, candidatos à
próxima visita.
85 AED (IST/DEEC)
Grafos – Procura generalizada (GS) (2)
Assim sendo, a estratégia genérica de procura em grafos é a
seguinte:
Tomar um qualquer vértice como inicial e criar a “franja” colocando lá
esse vértice.
Enquanto a “franja” não estiver vazia
Mover ao longo de uma aresta a partir da “franja”.
Se o vértice a que se chega não tiver sido visitado, visitá-lo a colocar na
“franja” todos os vértices não visitados que lhe são adjacentes.
Esta estratégia garante que todos os vértices de um grafo
ligado serão visitados.
Quando usamos uma pilha para modelar a “franja” temos DFS.
Quando usamos uma fila, temos BFS.
86 AED (IST/DEEC)
Grafos – Implementação de procura
generalizada – (lista de adjacências)
#define pfs search
87 AED (IST/DEEC)
Grafos – Propriedade da GS
Propriedade
Procura generalizada em grafos visita todos os vértices e arestas de um
grafo num tempo proporcional a 𝑉2 para matrizes de adjacências e
proporcional a 𝑉 + 𝐸 para listas de adjacências;
mais, no pior caso, o tempo necessário para 𝑉 inserções, 𝑉 remoções e
𝐸 actualizações numa fila generalizada de tamanho 𝑉.
Demonstração
A primeira parte não depende da implementação da fila generalizada,
pelo que se aplica trivialmente.
O tempo extra explicitado decorre naturalmente da implementação de
uma fila generalizada.
88 AED (IST/DEEC)
Grafos – Síntese da aula 3
Procura em grafos
Analogia com a exploração de labirintos; Estratégia de Tremaux
Procura em profundidade - DFS
Exemplo de execução; Implementação para matrizes de adjacências e
por listas de adjacências; Comparação; Propriedades
Procura em largura – BFS
Implementação por matrizes de adjacências; Exemplo de execução;
Propriedades; Implementação alternativa para matrizes de adjacências
Procura generalizada em grafos
Descrição; Implementação; Propriedades
89 AED (IST/DEEC)
Grafos – Árvores mínimas de suporte
Definição – Uma árvore mínima de suporte (MST) de um
grafo ponderado é o conjunto de arestas ligando todos os
vértices, tais que a soma dos pesos das arestas é, pelo menos,
tão baixa quanto a soma dos pesos de qualquer outro
conjunto de arestas ligando todos os vértices.
90 AED (IST/DEEC)
Grafos – Representação de grafos
ponderados (1)
A representação dos pesos associados às arestas em grafos
ponderados pode ser feita por:
A matriz de adjacências deixa de ser booleana, para passar a conter o
valor associado às arestas – requer sentinela para vértices não
adjacentes.
Cada elemento da lista de adjacências passa a conter um campo
adicional com o peso da aresta, para além do campo identificador do
vértice.
No caso da representação das arestas ter-se-á que adicionar um campo
para o peso.
typedef struct {int v, int w, double wt;} Edge;
Edge *EDGE(int, int, double);
Estas definições são incluídas no par de ficheiros GRAPH.h/GRAPH.c (como
e o quê em cada?) anteriormente introduzido.
91 AED (IST/DEEC)
Grafos - Implementação de ADT
(matriz de adjacências)
#include <stdlib.h>
#include “GRAPH.h” Grafos Ponderados
struct graph {int V; int E; double **adj;};
Graph *GRAPHinit(int V)
{
Graph *G = malloc(sizeof (graph *));
G->V = V; G->E = 0;
G->adj = MATRIXdouble(V, V, maxWT);
return G;
}
92 AED (IST/DEEC)
Grafos – Propriedades das MST (1)
Propriedade 1 – Dada uma divisão de vértices de um grafo em
dois conjuntos, qualquer árvore mínima de suporte (MST)
desse grafo contém uma aresta de menor peso que liga um
vértice de um dos conjuntos a algum dos vértices do outro.
Demonstração
Por redução ao absurdo.
Suponha-se que não há ou que não é de menor peso.
Se não existir, não é uma árvore de suporte.
Se não for de menor peso, então seja 𝑠 a aresta de menor peso que liga
vértices dos dois conjuntos. Esta aresta não pertence à MST.
Adicione-se a aresta 𝑠. O grafo obtido possui agora um ciclo e esse ciclo
contém também a aresta 𝑡 que liga os dois conjuntos.
Retirando a aresta 𝑡 obtém-se uma MST de menor peso. Não é?
93 AED (IST/DEEC)
Grafos – Exemplo (1)
G G
1 2 3 1 2 3
4 5 8 4 5 8
6 7 6 7
94 AED (IST/DEEC)
Grafos – Propriedades das MST (2)
Propriedade 2 – Dado um grafo 𝐺, considere-se o grafo 𝐺’ que
se obtém adicionando uma aresta 𝑒 a 𝐺. Adicionar 𝑒 à MST de
𝐺 e retirar a maior aresta do ciclo assim criado, gera a MST de
𝐺’.
Demonstração:
Se 𝑒 é maior que todos as outras arestas do ciclo, não pode pertencer à
MST de 𝐺’ (ver propriedade anterior): retirando 𝑒 de tal MST partiria o
grafo em dois e 𝑒 não seria a mais curta aresta entre essas duas partes,
porque alguma outra aresta do ciclo faz essa ligação e possui menor
peso.
Caso contrário, seja 𝑡 a maior aresta do ciclo criado com a adição de 𝑒.
Retirando 𝑡 à MST original gera duas partes em que todas as restantes
arestas são menores que 𝑡.
Logo, a menor aresta que liga essas duas partes é a aresta 𝑒.
95 AED (IST/DEEC)
Grafos – Exemplo (2)
Nova aresta
Árvore Mínima de Suporte
G
2 G
1 3 2
1 3
8
4 5 8
4 5
6 7
6 7
98 AED (IST/DEEC)
Grafos – Outra solução para a MST
Ideia 2 – Construir a árvore mínima de suporte adicionando
arestas por ordem crescente do seu valor, desde que a nova
aresta não forme um ciclo, parando assim que se tiverem
adicionado 𝑉 − 1 arestas.
Este método é conhecido com o Algoritmo de Kruskal.
Propriedade – O algoritmo de Kruskal calcula correctamente
a MST.
Demonstração (esboço)
Mostra-se por indução que o método constrói uma floresta de sub-
MST’s.
Sempre que se adiciona uma aresta que feche um ciclo, só pode ser a
maior desse ciclo – Propriedade 2.
Caso contrário, a aresta adicionada liga duas árvores e é a menor a fazer
essa ligação – Propriedade1.
99 AED (IST/DEEC)
Grafos – Outra mais...
Ideia 3 – Começar por ligar cada vértice ao seu vizinho mais
próximo, criando, no máximo, 𝑉/2 árvores. Depois, ligar cada
árvore à outra árvore que lhe estiver mais próxima. Etc.
G G G
1 4 1 1
4 4
0 2 0 2 0 2
5 6 3 5 6 3 5 6 3
3 3 3
3 4 7 7 3 4 7 7 3 4 7 7
2 2 2
6 3 6 3 6 3
4 4 4
5 7 5 7 6 5 7 6
6
G G
4 1 1
4
0 2 0 2
5 6 3 5 6 3
3 3
3 4 7 7 3 4 7 7
2 2
6 3 6 3
4 4
5 7 6 5 7 6
106 AED (IST/DEEC)
Grafos – Árvore de procura (Alg. Prim)
0
4
∞
G 1 ∞ 3 ∞
1 ∞ ∞ 7
4 2 3 6
4 5
0 2
5 6 3
3
3 4 7 7
2
6 3
4
5 7 6
0
4
∞
G 1 3 ∞
1 ∞ 7
4 3 6
5
0 2
5 6 3 6 2
3 2 4
3 4 7 7
2
6 3
4
5 7 6
0
4
∞
G 1 3
1 7
4 3
0 2
5 6 3 6 2
3 2 4
3 4 7 7
2 6 3
6 3
4 5 6
5 7 6
0
4
G 1 3
4 1
3
0 2
5 6 3 6 2
3 2 4
3 4 7 7
2 6 3
6 3
4 5 6
5 7 6
4
7
0
4
G 1 3
4 1
3
0 2
5 6 3 6 2
3 2 4
3 4 7 7
2 6 3
6 3
4 5 6
5 7 6
4
7
0
4
G 1 3
4 1
3
0 2
5 6 3 2
3 4
3 4 7 7
2 6 3
6 3
4 5 6
5 7 6
4
7
3
2
0
4
G 1 3
4 1
3
0 2
5 6 3 2
3 4
3 4 7 7
2 6 3
6 3
4 5 6
5 7 6
4
7
3
2
0
4
G 1 3
4 1
3
0 2
5 6 3 2
3 4
3 4 7 7
2 6 3
6 3
4 5 6
5 7 6
4
7
3
2
G G G
4 1 1 4 1
4
0 2 0 2 0 2
5 6 3 5 6 3 5 6 3
3 3 3
3 4 7 7 3 4 7 7 3 4 7 7
2 2 2
6 3 6 3 6 3
4 4 4
5 7 6 5 7 6 5 7 6
G G
4 1 1
4
0 2 0 2
5 6 3 5 6 3
3 3
3 4 7 7 3 4 7 7
2 2
6 3 6 3
4 4
5 7 6 7
5 6
128 AED (IST/DEEC)
Grafos – Alg. de Kruskal
(Propriedade)
Propriedade – O algoritmo de Kruskal calcula a MST de um
grafo num tempo proporcional a 𝐸 lg 𝐸.
Demonstração
Esta propriedade é consequência do facto de o tempo de execução
incluir uma ordenação de 𝐸 arestas seguida de 𝐸 operações procura e
𝑉 − 1 operações de união.
PORQUÊ?
Se utilizarmos os melhores algoritmos para cada uma das operações
identificadas, tais como “heapsort” para a ordenação e procura-união
ponderada com compressão de caminho para a conectividade, o custo
da ordenação domina.
nn[1*] (6,7,4)
a[h].wt < nn[j].wt ✓
nn[2*] (6,7,4)
a[N] a[h]; N 3
Demonstração:
Dado que o número de sub-árvores na floresta se reduz, pelo menos, a
metade em cada fase, o número de fases não é maior que lg 𝑉.
O tempo de cada fase é, no máximo, proporcional ao custo de 𝐸
operações de procura.
Observações:
A expressão acima é bastante conservadora, na medida em que ignora a
redução de arestas ocorrida em cada fase.
Concebido em 1926 e desde os anos 80 a base para o desenvolvimento
de algoritmos eficientes para MST’s, assim como para algoritmos
paralelos