Beruflich Dokumente
Kultur Dokumente
1
CONTEÚDO
0. INTRODUÇÃO
2. ALGORITMOS EM GRAFOS
2.1 Algoritmos de busca
2.2 Algoritmos Clássicos
2.3 Exercícios Propostos
3. PROBLEMAS NP-COMPLETOS
2
0. INTRODUÇÃO
3
executada do algoritmo e determina-se uma função t(n), que dá a variação do
tempo de execução em função de n, o tamanho da entrada.
Exs:
4
0.2 Bibliografia recomendada
5
1. CONCEITOS BÁSICOS SOBRE GRAFOS
SAL
BH
SP RIO
POA
SAL
BH
60
50 40 60
20
SP RIO
40 45
POA
6
Novas questões, então, poderiam ser formuladas, como:
d) Qual a maneira mais barata para se ir de BH para Salvador?
e) Qual a maneira mais rápida para esse mesmo percurso?
f) Qual o local ideal para se fazer uma Congresso, supondo-se que se
conheça o número de congressistas de cada cidade?
b) Fluxograma de um programa
Um grande número de diagramas, tais como fluxogramas para programas
podem ser expressos também por um grafo. Veja-se o exemplo a seguir:
I 1
i←0
2
i > 10 S
i ← i+1 3 4
N
i = 20 S F 5 7
N
6
a ← a+1
c) Relação binária
Pode-se usar um grafo para representar uma relação binária, como no exemplo
a seguir, onde a relação binária R é definida em S = {1, 2...10}, de forma que
xRy sse x divide y.
7
6
10 2 4 8 9
3
5 1 7
d) Rede de comunicações
Se o grafo do primeiro exemplo representasse, agora, uma rede de
comunicações:
SAL
BH
SP
RIO
POA
A seguir, são resumidas uma série de aspectos conceituais ligados a grafos. Tal
resumo foi retirado do Projeto Final, em andamento, dos alunos
8
• David Sotelo Pinheiro da Silva
• Sérgio Fernando Oliveira Theodoro dos Santos
Exemplo 1:
Seja G(V,E) onde V = {1, 2, 3} e E = { (1,2),(2,3)}. Como V é finito e não vazio e
todos os elementos de E são pares não-ordenados de V, então G(V,E) é um
grafo. Os vértices do grafo são 1,2 e 3. As arestas do grafo são (1,2) e (2,3).
Exemplo 2:
Seja G(V,E) onde V = {1, 2, 3} e E = { (1,2),(2,3),(1,4)}. Neste caso, V é finito e
não vazio, mas o elemento (3,4) ∈ E não é composto por elementos de V, uma
vez que 4 ∉ V. Portanto G(V,E) não é um grafo.
9
Exemplo 3:
Seja G (V,E) onde V = { 1, 2, 3} e E = { (1,3), (3,2) }. Então:
a) n = |V| = 3
b) m = |E| = 2
c) Os vértices 2 e 3 são extremidades da aresta (2,3), sendo adjacentes. A
aresta (2,3) é incidente aos vértices 2 e 3.
d) As arestas (3,5) e (4,3) são adjacentes, pois possuem um extremo em
comum (o vértice 3).
Exemplo 4:
Seja G (V,E) onde V = {1, 2, 3} e E = {(1,2), (1,3), (2,3)}. G(V,E) pode ser
representado geometricamente de várias formas:
1 3
2
2 3
1
Exemplo 5:
Sejam G1(V1,E1) e G1(V2,E2) , onde:
V1 = {1,2,3} E1 = {(1,2),(1,3)}
V2 = {5,6,7} E2 = {(5,6),(6,7)}
Laço – Um laço é uma aresta do tipo e = (v,v). Ou seja, uma aresta que une um
vértice com ele mesmo. A existência de uma aresta deste tipo vai de encontro
10
com a definição básica de grafos mas representa um desvio de definição útil
para alguns casos. Laços não existem em grafos simples.
Exemplo 6:
Seja G(V,E) tal que V = {1,2,3} e E = { (1,2),(2,3),(1,3),(2,2)}
A aresta (2,2) une o vértice 2 com ele mesmo, trata-se portanto de um laço.
1 2
Exemplo 7:
No multigrafo abaixo existem 2 arestas incidentes aos vértices 2 e 3.
1 2
Exemplo 8:
Seja G(V,E) tal que V = {1,2,3,4} e E = { (2,3),(3,4),(1,3),(2,4)}
2
1
11
Grau(2)=Grau(3)= 3, Grau(4) = 3 e Grau(1) = 1.
Exemplo 9:
O grafo apresentado no exemplo 9 não é regular, uma vez que nem todos os
seus vértices apresentam grau idêntico.
1 2
Exemplo 10:
Considere o grafo representado abaixo:
2 1 4
3 5
12
Comprimento de um caminho – É o número de arestas encontradas em um
passeio.
Exemplo 11:
Seja G(V,E) onde V={1,2,3,4} e E = {(1,2),(2,3),(3,4)}
Exemplo 12:
Seja G(V,E) onde V={1,2,3} e E = {(1,2),(2,3),(3,1)}
Exemplo 13:
Seja G(V,E) onde V={1,2,3} e E = {(1,2),(2,3)}
Exemplo 14:
Seja G(V,E) onde V={1,2,3,4} e E = {(1,2),(1,4),(4,3),(3,2)}
1 4
2 3
13
A seqüência 1, (1,4), 4 ,(4,3), 3, (3,2), 2, (1,2), 1 é um circuito, uma vez que os
vértices de origem e destino são idênticos. Podemos observar que apenas os
vértices de origem e destino do circuito (1 e 2) se repetem e que o
comprimento do passeio é 3. Trata-se portanto de um ciclo.
Exemplo 15:
Seja G(V,E) onde V={1,2,3,4,5,6} e E = {(1,2),(1,3),(2,4),(3,5),(3,6)}
2 4
1
5
3
Exemplo 16:
Seja G(V,E) onde V={1,2,3,4} e E = {(1,3),(1,4),(4,3),(3,2)}
1 4
2 3
Ciclo Hamiltoniano – Ciclo que passa por cada vértice de um grafo exatamente
uma vez.
14
Exemplo 17:
Seja G(V,E) o grafo representado abaixo:
5
4
1
2 3
Grafo Conexo – Grafo onde existe um caminho entre cada par de vértices.
Grafo Desconexo – Grafo onde não existe caminho entre pelo menos um par de
vértices.
15
Articulação – Um vértice w ∈V é denominado articulação quando sua remoção
desconecta o grafo a qual pertence.
Grafo Completo – Grafo em que existe uma aresta entre cada par de vértices
do mesmo.
16
Kn – Notação utilizada para designar um grafo completo com n vértices.
17
Floresta – Uma floresta é um conjunto de árvores.
18
Grau de saída de um vértice – Seja D(V,E) um digrafo e um vértice v ∈V. O
grau de saída de v é o número de arestas divergentes de v.
19
2 Algoritmos em grafos
a) Matriz de Adjacências
Utiliza-se uma matriz n x n de inteiros ou booleanos, onde cada célula (i,
j) da matriz indica a existência de aresta entre os vértices i e j. Quando se
tratar de grafos simples, uma aresta aparece duplicada nessa matriz, tanto na
célula (i, j), quanto na (j, i). Quando se trata de digrafos, cada aresta será
indicada apenas em uma célula. Esta estrutura permite também a indicação de
laços, mas não pode representar multigrafos.
Esta representação é adequada quando ou o grafo é pequeno ou é denso,
já que precisa de espaço da ordem de O(n2).
Ex: 1 2 3 4 5
5 1 0 1 0 1 1
4 2 1 0 1 0 0
1 3 0 1 0 1 0
4 1 0 1 0 1
2 3 5 1 0 0 1 0
20
b) Listas de Adjacências
Neste caso, cria-se uma lista de adjacências para cada vértice. O mais
adequado é que estas listas sejam listas encadeadas, de forma que a estrutura
completa consta de um vetor composto, com um ponteiro para a lista
encadeada, em cada célula do vetor.
Tal como no caso anterior, num grafo simples uma aresta fica
representada duas vezes; num digrafo, apenas uma. A estrutura pode ser
usada para representar qualquer tipo de grafo. É especialmente adequada para
grafos grandes e esparsos.
Ex:
1 2 4 5
5
2 1 3
4
1
3 2 4
4 1 3 5
2 3 5 1 4
c) Matriz de Incidências
A idéia é criar uma matriz n x m, onde as linhas referem-se aos vértices
e as colunas, às arestas. A representação é análoga à de matriz de adjacências.
Esta representação é mais rara e somente é vantajosa para grafos densos.
21
Busca_Em_Profundidade; (A 7.1)
Desmarcar vértices;
Para i de 1 a n:
Se vértice i não marcado Então
BP(i);
Fs;
Fp;
BP(i):
Marcar i;
Para w = vizinho de i:
Se w não marcado Então
BP(w);
Fs;
Fp;
Fim;
B C
22
A
F G D
23
Busca_Em_Largura(); (A 7.2)
Desmarcar vértices;
Para i de 1 a n:
Se vértice i não marcado Então
Definir uma fila Q vazia;
Marcar i;
Enfilar (i,Q);
Enquanto (Q ≠ ∅):
Seja v o primeiro elemento de Q;
Para w vizinho de v:
Se w não é marcado Então
Marcar w; Enfilar (w,Q);
Fs;
Fp;
Desenfilar (v,Q);
Fe;
Fs;
Fp;
Fim;
Retornando ao mesmo grafo do exemplo anterior,
E
D
A
B C
24
A
B
C
F D G
Tal como no exemplo anterior, podemos também ter mais de uma árvore
de largura. Além disso, todas as propriedades de um grafo mencionadas,
também podem ser descobertas neste tipo de busca. Adicionalmente, obtém-se
todas as distâncias do vértice inicial da busca aos demais vértices, o que pode
ser algo necessário em muitas aplicações.
A complexidade do algoritmo também depende do tipo de representação
utilizada e é a mesma que a da busca em profundidade, ou seja, O(n+m) para
representação através de listas de adjacências e O(n2) para representação
através de Matriz de Adjacências.
25
ComponentesFC;
Limpa matriz ET; nf ← 0;
Para i de 1 a n:
Se (V[i] não marcado) Então
BP(i);
Fp;
Para i de 1 a n:
Para j de 1 a n:
Se (E[i,j] = 1) Então
ET[j,i] ← 1;
Fp;
Fp;
Desmarcar vértices; nc ← 0;
Para i decrescendo de n a 1:
Se (V[F[i]] não marcado) Então
nc ← nc + 1;
BPE[F[i]);
Fp;
Fim;
BP(v);
Marcar v;
Para w vizinho de v, não marcado:
BP(w);
Fp;
nf ← nf + 1; F[nf] ← v;
Fim;
BPE(v);
Marcar v; VC[v] ← nc;
Para w vizinho de v, não marcado:
BPE(w);
Fp;
Fim;
O algoritmo é exemplificado a seguir.
26
G H A B
F D C
E
v f fi
1 (A) 5 5
2 (B) 4 3
3 (C) 2 4
4 (D) 3 2
5 (E) 1 1
6 (F) 8 8
7 (G) 7 7
8 (H) 6 6
O digrafo DT é o seguinte:
G H A B
F
E D C
F A D C
H B E
27
2.2 Algoritmos clássicos
Neste tópico são apresentados os seguintes algoritmos clássicos de
grafos:
a) Ordenação Topológica
b) Coloração aproximada
c) Circuito Euleriano
d) Caminho mínimo
E
D
A
B C
28
Ordenação_Topológica(); (A 7.3)
Q←∅;
Para todo v com grau de entrada 0 em D: Enfilar (v, Q); Fp;
Enquanto (Q ≠ ∅):
Seja w o primeiro elemento de Q;
Desenfilar (w, Q);
Colocar w na ordenação;
Retirar w de D;
Para v ∈ D, efetuar:
Se (grau de entrada de v = 0) Então
Enfilar (v, Q);
Fs;
Fp;
Fe;
Fim;
D, F, E, C, A, G, B
29
vértices de uma dessas k partições, ele recebe a mesma cor dessa partição.
Caso contrário, ele recebe a cor k+1. O algoritmo é:
Coloração_Aproximada() (A 7.4)
Ordenar V = { v1, v2, ... vn} em ordem não crescente de graus;
Para i de 1 a n:
Part[i] ← ∅;
Fp;
Colorir v1 com a cor 1;
Part[1] ← { v1 };
Para i de 2 a n:
r ← Min { j | Part[j] ∩ Adj( vi ) = ∅ }
Colorir vi com a cor r;
Part[r] ← Part[r] U { vi };
Fp;
Fim;
(a) (b)
A coloração (a) foi obtida pelo algoritmo, após a seguinte ordenação dos
vértices: A, B, C, D, E, F e usa 3 cores; A coloração (b) é uma das colorações
mínimas possíveis, com 2 cores.
30
Para exibir o circuito Euleriano, o algoritmo a seguir utiliza uma técnica
destrutiva, pois vai eliminando arestas do grafo. Caso o grafo necessite ser
mantido, trabalha-se com uma cópia do mesmo. O algoritmo inicia o processo
em um vértice dado e empilha vértices, sucessivamente, sempre um vizinho do
último vértice empilhado. Cada vértice empilhado corresponde a uma aresta
considerada, que é, então, eliminada do grafo, atualizando-se os graus do
mesmo. Quando se chegar a um vértice com grau 0, desempilham-se vértices
com grau 0, reiniciando o processo a partir do vértice do topo da pilha. Ao
final, a ordem de desempilhamento é o passeio procurado.
O algoritmo é apresentado a seguir.
CircuitoEuleriano (v);
Inicio
PUSH(v);
Enquanto (topo ≠ 0):
w ← ProxVertice (v); Elimina (v, w);
PUSH (w);
Enquanto (topo ≠ 0) e (D[P[topo]] = 0):
w ← POP;
Imprimir (w);
Fe;
v ← P[topo];
Fe;
Fim;
E
D
A
B C
F G
31
A determinação de caminhos mínimos entre vértices tem, também, uma
enorme gama de aplicações. O problema pode ser colocado de várias formas,
algumas ligeiramente diferentes das outras, o que pode levar a soluções
diferentes. A primeira variante que vamos considerar é quando as arestas não
são ponderadas e queremos simplesmente determinar o menor caminho entre
os dois vértices, apenas contanto o número de vértices do caminho. Este
problema já foi resolvido, tanto para grafos simples quanto para digrafos,
através da busca em largura.
A variante mais geral, aplicada tanto para grafos quanto para digrafos,
trata de encontrar um caminho mínimo ponderado entre os dois vértices, onde
os pesos das arestas são positivos. O algoritmo que será apresentado,
desenvolvido por Dijkstra, é feito para digrafos.
Este algoritmo parte de determinado vértice e determina os caminhos
mínimos para todos os demais vértices alcançáveis a partir do mesmo. Ele é um
algoritmo guloso que, inicialmente, supõe distância infinita de todos os vértices
àquele escolhido. Ao longo do algoritmo vai corrigindo essa avaliação de
distâncias, à medida que vai obtendo mais informações sobre os caminhos. A
cada passo, escolhe e marca um novo vértice, aquele com a menor distância
avaliada até o momento. Para o vértice marcado a distância é fixada em
definitivo e são reavaliadas as distâncias mínimas de seus vizinhos ainda não
marcados.
Quando se quiser utilizar o algoritmo apenas para determinar a distância
entre dois determinados vértices, o algoritmo inicia marcando o primeiro
desses vértices e para quando o segundo vértice for o escolhido para
marcação.
O algoritmo é o seguinte:
32
Menor_Caminho(y); (A 7.6)
Para todo v ∈ V efetuar:
Desmarcar v;
Distância[v] <- ∞ ;
Fp;
Distância[y] <- 0;
Enquanto existir vértice não marcado, efetuar:
w <- vértice não marcado com Distância mínima;
Marcar w;
Para todas as arestas (w,z) efetuar:
Se (Distância[w] + peso[w,z] < Distância[z]) Então
Distância[z] <- Distância[w] + peso[w,z];
Fs;
Fp;
Fe;
Fim;
B 1 C 4 D
2 1 1
A 5 H 6 I
1 2 2
E 9 F 5 G
A B C D E F G H I
E 0 2 ∞ ∞ 1 ∞ ∞ 5 ∞
B 0 2 ∞ ∞ 1 10 ∞ 5 ∞
C 0 2 3 ∞ 1 10 ∞ 5 ∞
H 0 2 3 7 1 10 ∞ 4 ∞
F 0 2 3 7 1 6 ∞ 4 10
D 0 2 3 7 1 6 11 4 10
I 0 2 3 7 1 6 11 4 8
G 0 2 3 7 1 6 10 4 8
33
Para utilizar o algoritmo quando o digrafo não é ponderado, basta
colocar-se peso 1 para todas as arestas do mesmo. O algoritmo, na forma em
que está escrito, serve também para grafos simples, sem nenhuma
modificação, até porque pode-se considerar que a representação do grafo
simples significa a representação de um digrafo, com cada aresta do grafo
simples duplicada nas duas direções.
34
3. PROBLEMAS NP-COMPLETOS
Algoritmos 1 2 3 4 5
Complexidade 33n 46nlgn 13n2 3.4n3 2n
Tam: entrada
10 ,00033 ,0015 ,0013 ,0034 ,001
100 ,003 ,03 ,13 3,4 1016 anos
1.000 ,033 ,45 13 ,94 h -
10.000 ,33 6,1 22 min 39 dias -
100.000 3,3 1,3 min 1,5 dias 108 anos -
Exemplos:
-Ordenação de Dados
-Buscas e atualização em árvores
-Buscas em grafos
-Ciclos Eulerianos
-Problemas com solução gulosa, em geral
-Problemas com solução por Programação dinâmica em geral
-Programação linear
Exemplos:
-Torre de Hanoi
-Geração de Permutações
35
3.3 Problemas ainda não classificados
Existe uma grande classe de problemas para os quais não se sabe ainda
se existe algoritmo polinomial ou não .
Exemplos:
-Partição (Soma de subconjuntos)
-Mochila
-Empacotamento
-Programação inteira
-Caixeiro viajante
-Ciclo Hamiltoniano
-Coloração de vértices em grafos
-Satisfatibilidade
-Clique Máxima em grafos
-Conjunto independente máximo em grafos
36
Uma atribuição de cores aos vértices do grafo.
Esse certificado tem tamanho equivalente ao tamanho do grafo (portanto
seu tamanho é polinomial em função da entrada). Além disso, pode-se
verificar, em tempo polinomial se o certificado é correto. (Basta fazer a
atribuição de cores dada pelo certificado e checar se não existem 2
vizinhos com a mesma cor. Além disso deve-se verificar se o número de
cores usada é ≤ k).
Notar que nada é exigido em relação à resposta NÃO.
37
Ex: Ciclo Hamiltoniano reduz-se, polinomialmente, a Caixeiro Viajante.
CH: Dado G, existe ciclo Hamiltoniano em G?
CV: Dado G´, completo, com arestas ponderadas, existe ciclo Hamiltoniano
com peso total ≤ k?
Transformação de CH em CV:
A partir de G para CH, cria-se G´ completo para CV, com os seguintes
pesos: para cada aresta (v,w) de G´, se ela existir em G, seu peso = 1;
senão, seu peso = 2. k é feito = |V(G)|.
Problemas em aberto:
a) P = NP?
38
39