Caminhos Mais Curtos Fluxo Máximo Árvores Geradoras Mínimas Túlio Toffolo – www.toffolo.com.br Marco Antônio Carvalho – [email protected] BCC402 – Aula 14 Algoritmos e Programação Avançada Plano da Aula • Caminhos Mais Curtos • Algoritmo de Dijkstra • Algoritmo de Floyd • Fluxo Máximo • Algoritmo de Ford Fulkerson • Árvores Geradoras Mínimas • Algoritmo de Kruskal • Algoritmo de Prim • Otimização dos algoritmos 2 CAMINHOS PROGRAMAÇÃO DE TRIPULAÇÕES MAIS CURTOS Caminhos mais Curtos • Dados: grafo G=(V,A) orientado e distância cij associada ao arco (i,j) ∈ A. Problema: Obter o caminho mais curto entre dois nós s e t. • O comprimento de um caminho é igual à soma dos comprimentos (distâncias) dos arcos que formam o caminho. • A “distância” ou “comprimento” de um arco pode ter diversas interpretações Exemplo 1: Dado um mapa rodoviário, determinar a rota mais curta de uma cidade a outra. 4 Caminhos mais Curtos Exemplo 2: Construção de uma estrada entre duas cidades A e K. O grafo abaixo representa os diversos trechos possíveis e o custo de construção de cada um. Determinar o trajeto ótimo cujo custo de construção seja mínimo (corresponde a achar o caminho mais curto de A a K em relação a estes custos). B 2 8 5 C D Solução: 4 4 F I 2 4 4 7 H 4 4 5 A E 6 5 K 2 4 2 G 4 J A–D–G–I–K custo = 7 + 2 + 2 + 5 = 16 5 Caminhos mais Curtos • Condição de existência: Caminho de i a j contendo um circuito w: k j i w Comprimento do caminho = comprimento (i → k) + comprimento (w) + comprimento (k → j) Qual é o comprimento do caminho mais curto de i a j se o comprimento do circuito w é negativo? 6 Caminhos mais Curtos Condição de existência: não há circuitos de comprimento negativo. A solução ótima (caminho mais curto) sempre será um caminho elementar (sem ciclo). 7 Caminhos mais Curtos " Caminho mais curto: - De um nó a outro - De um nó a todos os demais - Entre todos os pares de nós de um grafo 8 Caminhos mais Curtos Caminho mais curto do nó 1 a cada nó do grafo G=(V,A) Hipótese: todas as distâncias cij são positivas: cij ≥ 0, ∀(i,j) ∈ A • Algoritmo de Moore-Dijkstra (1957-1959) π*(i) = comprimento do caminho mais curto do nó 1 ao nó i Em especial, π*(1)=0 (distâncias positivas). " " Algoritmo com n-1 iterações No início de cada iteração, o conjunto V de nós está particionado em dois subconjuntos S e S, com o nó 1 em S. S ∩S =φ S ∪ S =V 9 Caminhos mais Curtos – Cada nó i ∈ V possui um rótulo π(i ), que verifica a seguinte propriedade: Se i ∈ S ⇒ π (i ) = π * (i ) Se i ∈ S ⇒ π (i ) ≥ π * (i ) – π (i ) = min{π (k ) + c ki } k ∈S k ∈Γ i− π (i ), i ∈ S , dá o valor do caminho mais curto de 1 a i sob a restrição de que todos os nós utilizados (exceto o próprio i ) pertençam a S. π (a ) a π (b ) 1 b cai cbi π (c ) c π (i ) i cci S S 10 Caminhos mais Curtos Teorema: Seja o nó j ∈ S tal que π ( j ) = min π (i .) i ∈S Então π * ( j ) = π ( j ) , isto é, o comprimento do caminho mais curto do nó 1 ao nó j é igual a π ( j ) . Demonstração: – Por construção, certamente existe um caminho de 1 até j com comprimento π(j). – Suponhamos que exista outro caminho de 1 a j de comprimento menor do que π(j). – Dividamos este caminho em duas partes: - P1 é a parte inicial, do nó 1 ao nó L, onde L é o primeiro nó de S encontrado - P2 é a parte final, do nó L ao nó j 11 Caminhos mais Curtos – comprimento de P1 ≥ π(L) ≥ π(j) comprimento de P2 ≥ 0 Logo, o comprimento de P1 + P2 ≥ π(j). 12 CAMINHOS MAIS CURTOS PROGRAMAÇÃO ALGORITMO DE DIJKSTRA DE TRIPULAÇÕES Caminhos mais Curtos Algoritmo de Moore-Dijkstra Inicializar S ← {2,3,...,n}, S ← {1}, π(1)← 0, π(j)← c1j se j∈Γ1+ +∞ caso contrário Enquanto S ≠ ∅ faça Selecionar j∈S tal que π(j)= mini∈S{π(i)} S ← S – {j} Para ∀i∈S e i∈Γj+ faça π(i) ← min{π(i), π(j)+cji} fim_enquanto 14 Caminhos mais Curtos • O algoritmo de Moore-Dijkstra constrói progressivamente o conjunto dos nós mais próximos de 1. • Construção de uma arborescência com raiz em 1 que define os caminhos mais curtos do nó 1 a cada nó do grafo. 15 Caminhos mais Curtos Exemplo: 4 4 7 1 1 5 1 5 5 2 2 3 S = {1} S = {2,3,4,5,6} 2 3 6 7 π(1) = 0 π(2) = 7 π(3) = 1 π(4) = π(5) = π(6) = +∞ ITERAÇÃO 1 4 π*(1) = 0 1 1 5 1 3 π*(3) = 1 5 2 2 7 4 5 j=3 S = {2,4,5,6} 6 π(2) = min{7, 1+5} = 6 π(5) = min{∞, 1+2} = 3 π(6) = min{∞, 1+7} = 8 2 7 3 16 Caminhos mais Curtos 4 π*(1) = 0 1 1 5 1 3 1 1 3 π*(3) = 1 3 5 π(2) = min{6, 3+2} = 5 π(4) = min{∞, 3+5} = 8 ITERAÇÃO 3 π*(5) = 3 j=2 S = {4,6} 5 2 7 j=5 S = {2,4,6} 6 4 1 5 π*(5) = 3 2 2 2 7 π*(1) = 0 4 ITERAÇÃO 2 5 7 π*(3) = 1 π*(2) = 5 5 2 2 7 4 3 6 π(4) = min{8, 5+4} = 8 π(6) = min{∞, 5+1} = 6 17 Caminhos mais Curtos π*(2) = 5 1 1 5 1 4 5 2 2 7 π*(1) = 0 4 3 5 2 3 ITERAÇÃO 4 j=6 S = {4} π(4) = 8 6 7 π*(3) = 1 π*(5) = 3 π*(6) = 6 π*(4) = 8 π*(2) = 5 1 1 5 1 4 3 π*(3) = 1 5 2 2 7 π*(1) = 0 4 π*(5) = 3 5 2 7 3 ITERAÇÃO 5 j=4 S={} 6 π*(6) = 6 18 Caminhos mais Curtos 4 1 Iteração 1 5 2 π 3 2 3 3 5 2 2 1 3 4 3 6 4 7 Início 1 2 3 4 5 6 1 0 0 0 0 0 0 0 2 4 4 4 4 4 4 4 3 2 2 2 2 2 2 2 4 ∞ 5 5 5 5 5 5 ∞ 4 4 4 4 4 4 ∞ ∞ 7 7 7 7 7 ∞ ∞ 7 7 7 7 7 nó 5 6 7 19 Caminhos mais Curtos • Número de operações (tempo): ~ n2 n-1 iterações, cada iteração busca o mínimo em uma lista com até n-1 elementos (vetor π) " Caminho mais curto do nó 1: → ao nó j → a todos os nós Mesma complexidade, mas critérios de parada diferentes. " Distâncias negativas: Caminho mais curto de 1 a 3? 2 3 3 1 -8 10 2 Resultado do algoritmo? 3 Por que? 20 Caminhos mais Curtos Algoritmo de Moore-Dijkstra para o caso com distâncias negativas Inicializar S ← {2,3,...,n}, S ← {1}, π(1)← 0, π(j)← c1j se j∈Γ1+ +∞ caso contrário Enquanto S ≠ ∅ faça Selecionar j∈S tal que π(j)= mini∈S{π(i)} S ← S – {j} Para ∀i∈Γj+ faça Calcular π* ← π(j)+ cji Se π* < π(i) então S ← S ∪ {i} π(i) ← π* fim-se fim-para fim-enquanto 21 CAMINHOS MAIS CURTOS PROGRAMAÇÃO ALGORITMO DE FLOYD DE TRIPULAÇÕES Caminhos mais Curtos • Dados: Grafo G=(V, A) orientado, |V | = n. Não há circuitos negativos. c = {cij}, j = 1,...,n, i = 1,...,n cij ≥ 0 cii = 0 cij = +∞, (i, j ) ∉ A Ak(i, j ) = valor do caminho mais curto de i a j podendo usar apenas nós numerados de 1 a k como nós intermediários. 23 Caminhos mais Curtos A0(i, j ) = cij : caminho mais curto de i a j usando no máximo o nó “0” (que não existe) como nó intermediário (caminho mais curto de i a j sem nós intermediários) Ak(i, j ) : pode usar o nó k ou não. Ak+1(i, j ) : pode usar o nó k+1 ou não. A0 → A1 A1 → A2 ... An-1 → An An(i, j ) = valor do caminho mais curto de i a j podendo usar qualquer nó de 1 a n como nó intermediário. 24 Caminhos mais Curtos • Se Ak+1(i, j ) não usa o nó k+1 como intermediário, então: Ak+1(i, j ) = Ak(i, j ) • Se Ak+1(i, j ) usa o nó k+1 como intermediário, então: Ak+1(i, j ) = Ak(i, k+1) + Ak(k+1, j ) Ak+1(i, j ) = min { Ak(i, j ), Ak(i, k+1) + Ak(k+1, j ) } 25 Caminhos mais Curtos Algoritmo de Floyd: Para i = 1,...,n faça Para j = 1,...,n faça A0(i,j) ← cij fim-para fim-para Para k = 1,...,n faça Para i = 1,...,n faça Para j = 1,...,n faça Ak(i,j) ← min{Ak-1(i,j), Ak-1(i,k) + Ak-1(k,j)} fim-para fim-para fim-para 26 Caminhos mais Curtos Exemplo: 6 1 2 4 3 11 0 4 11 0 4 11 C = 6 0 2 A0 = 6 0 2 +∞ 0 3 +∞ 0 3 2 3 0 4 11 0 4 6 0 4 6 A1 = 6 0 2 A2 = 6 0 2 A3 = 5 0 2 3 7 0 3 7 0 3 7 0 Teoriade Grafos 27 Caminhos mais Curtos • Algoritmo de Dijkstra: número de operações (tempo) ~ n2 n-1 iterações, cada iteração busca o mínimo em uma lista com até n-1 elementos (vetor π) • Algoritmo de Floyd: número de operações (tempo) ~ n3 Três comandos for de 1 até n um dentro do outro • Ou seja, o problema de calcular os caminhos mais curtos entre todos os pares de nós pode ser resolvido com a mesma eficiência aplicando-se n vezes o algoritmo de Dijkstra, uma vez a partir de cada nó inicial. 28 Otimizações: uso de Heaps Complexidade Amortizada Complex. “Real” Pairing Heap Fibonacci Heap isEmpty O(1) O(1) O(1) size O(1) O(1) O(1) getMax O(1) O(1) O(1) put O(1) O(log n) ** O(1) removeMax O(n) O(log n) O(log n) meld O(1) O(log n) ** O(1) remove O(n) O(log n) O(log n) increaseKey O(n) O(log n) ** O(1) Operação PROGRAMAÇÃO FLUXO MÁXIMO DE TRIPULAÇÕES Problema do Fluxo Máximo • Dados: Grafo G=(X,U) orientado ∀u ∈ U: capacidade c(u) 0 ≤ f(u) ≤ c(u) fonte S f sumidouro P • Problema: Obter um fluxo máximo de S a P respeitando as restrições de capacidade e as restrições de conservação de fluxo em cada nó. 31 Problema do Fluxo Máximo " Inserindo-se um arco de retorno, transforma-se um fluxo em uma “circulação”: S P f Exemplo: a 1, 1 1, 2 S 2, 4 capacidades c fluxos f 0, 5 P 3, 3 b 3, ∞ 32 Problema do Fluxo Máximo v, x = S f (u ) − ∑ f (u ) = ∑ u I u x uT u x : ( )= : ( )= I(u) 0, ∀x ≠ S, ∀x ≠ P -v, x ≠ P u T(u) Com o arco de retorno: f (u ) − ∑ f (u ) = 0, ∀x ∈ X ∑ uI u x uT u x : ( )= : ( )= 33 Problema do Fluxo Máximo Exemplo: a ∞ S 3 1 e 2 ∞ b c 2 ∞ 1 1 P 7 5 ∞ d ∞ " Capacidades associadas aos nós: 2 3 2 x 8 x1 7 8 c(x) 3 x2 7 34 FLUXO MÁXIMO ALGORITMO DE FORD FULKERSON Problema do Fluxo Máximo " Algoritmo de rotulação de Ford e Fulkerson (idéia básica) Início: fluxo viável (por exemplo um fluxo nulo) Iteração: Determinar um caminho C de S a P ao longo do qual nenhum arco esteja saturado. (isto é, f(u) = c(u)) Circuito Γ = C ∪ {(P,S)} Aumentar o fluxo ao longo dos arcos de Γ do valor δ = minu∈Γ[c(u)-f(u)] 36 Problema do Fluxo Máximo Exemplo: a 1 1 5 2 S P 1 3 4 b 32 1 2 3 Este fluxo (f=3) é máximo? Por que? Fluxo máximo = 4 37 Problema do Fluxo Máximo " A inexistência de um caminho aumentante no grafo original não quer dizer que não seja possível aumentar o fluxo. • Obter uma cadeia ligando S e P que, em conjunto com o arco de retorno (P,S) defina um ciclo Γ: Γ+: arcos de Γ orientados como (P,S) Γ-: arcos de Γ orientados no sentido oposto a (P,S) δ1= minu∈Γ+ [c(u) – f(u)] (aumento possível nos arcos de Γ+) δ2= minu∈Γ- [f(u)] " (redução possível nos arcos de Γ-) Melhorar a solução (aumentar o fluxo) somando δ = min{δ1, δ2} aos fluxos nos arcos de Γ+ e subtraindo δ aos fluxos nos arcos de Γ-. 38 Problema do Fluxo Máximo Exemplo: f(u) c(u) a Γ+ 1, 1 +1 S +1 1, X 2 0 P Γ -1 Γ+ Γ 3, 3 2, X 4 3 Γ+ 1 0, 5 X b +1 δ1 = 2 δ2 = 1 3, X ∞ 4 δ=1 39 Problema do Fluxo Máximo Algoritmo • Procedimento de rotulação para obter um ciclo Γ: Nó x → rótulo δ(x) " Rotulação direta: x marcado δ(x) com u = (x,y) f(u) < c(u) y não marcado Quantidade pela qual pode ser aumentado o fluxo de S a x seguindo uma cadeia cujo último arco é A(x) x u y δ(x) δ(y) = min { δ(x), c(u)-f(u) } A(y) = u 40 Problema do Fluxo Máximo " Rotulação inversa: x marcado δ(x) arco u = (y,x) f(u) > 0 y não marcado x u y δ(x) δ(y) = min { δ(x), f(u) } A(y) = u f(u) ← 0 ∀u ROTULAR(f,δ,A,Y) Enquanto δ > 0 faça ALTERAR_FLUXOS(f,δ,A) ROTULAR(f,δ,A,Y) fim-enquanto 41 Problema do Fluxo Máximo ROTULAR(f,δ,A,Y) δ, δ(S) ← +∞ Y ← {S} Enquanto P ∉ Y e δ > 0 faça Se ∃u =(x,y): x ∈ Y, y ∉ Y e f(u) < c(u) então Y ← Y ∪ {y} A(y) ← u δ(y) ← min {δ(x), c(u)-f(u)} Senão Se ∃u =(y,x): x ∈ Y, y ∉ Y e f(u) > 0 então Y ← Y ∪ {y} A(y) ← u δ(y) ← min {δ(x), f(u)} Senão δ ← 0 fim-enquanto Se P ∈ Y então δ ← δ(P) FIM-ROTULAR 42 Problema do Fluxo Máximo ALTERAR_FLUXOS(f,δ,A) x ← P f(P,S) ← f(P,S) + δ Enquanto x ≠ S faça u ← A(x) Se x = T(u) então f(u) ← f(u) + δ x ← I(u) Senão f(u) ← f(u) - δ x ← T(u) fim-enquanto FIM-ALTERAR_FLUXOS 43 Problema do Fluxo Máximo a 1, 1 Exemplo: 1, 0, 5 1, 2 0, S 2, 3, 4 P 3, 3 b 3, ∞ 4, Marcação: f(P,S) = 4 δ(S) = +∞ Y = {S} A(S) = (P,S) δ(b) = 2 Y = {S, b} A(b) = (S,b) δ(a) = 1 Y = {S, b, a} A(a) = (a,b) δ(P) = 1 Y = {S, b, a, P} A(P) = (a,P) δ=1 f(a,P) = 1 f(a,b) = 0 f(S,b) = 3 f(S,a) = 1 f(b,P) = 3 44 Problema do Fluxo Máximo a 1, 1 Exemplo: 1, 5 0, 2 S P 3, 3 3, 4 b 4, ∞ Marcação: δ(S) = +∞ Y = {S} δ(b) = 1 Y = {S, b} δ = 0, P ∉ Y FIM 45 Problema do Fluxo Máximo Exemplo: 20 2 15 15 15 4 5 1 5 12 3 15 4 9 15 7 8 6 8 10 6 8 12 8 15 ∞ δ(1) = +∞ Y = {1} A(1) = (7,1) δ(2) = 20 Y = {1, 2} A(2) = (1,2) δ(6) = 15 Y = {1, 2, 6} A(6) = (2,6) δ(7) = 15 Y = {1, 2, 6, 7} A(7) = (6,7) δ = 15 f(6,7) = 15 f(2,6) = 15 f(1,2) = 15 f(7,1) = 15 46 Problema do Fluxo Máximo Exemplo: 20 15 2 10 5 3 15 8 9 4 15 7 8 6 8 8 6 4 5 12 1 15 15 8 8 8 12 8 15 23 ∞ δ(1) = +∞ Y = {1} A(1) = (7,1) δ(3) = 10 Y = {1, 3} A(3) = (1,3) δ(4) = 9 Y = {1, 3, 4} A(4) = (3,4) δ(8) = 9 Y = {1, 3, 4, 8} A(8) = (4,8) δ(7) = 8 δ=8 Y = {1, 3, 4, 8, 7} A(7) = (8,7) f(8,7) = 8 f(4,8) = 8 f(3,4) = 8 f(1,3) = 8 f(7,1) = 23 47 Problema do Fluxo Máximo Exemplo: 20 2 15 20 5 5 5 10 3 15 8 9 4 15 7 5 8 6 8 8 6 4 5 12 1 15 15 8 8 8 12 8 23 28 ∞ δ(1) = +∞ Y = {1} A(1) = (7,1) δ(2) = 5 Y = {1, 2} A(2) = (1,2) δ(3) = 5 Y = {1, 2, 3} A(3) = (2,3) δ(5) = 5 Y = {1, 2, 3, 5} A(5) = (3,5) δ(7) = 5 δ=5 Y = {1, 2, 3, 5, 7} A(7) = (5,7) f(5,7) = 5 f(3,5) = 5 f(2,3) = 5 f(1,2) = 20 f(7,1) = 28 48 Problema do Fluxo Máximo Exemplo: 20 2 20 5 5 5 7 10 10 8 15 8 9 4 15 7 7 5 8 6 8 3 6 4 5 12 1 15 15 8 8 8 12 8 28 30 ∞ δ(1) = +∞ Y = {1} A(1) = (7,1) δ(3) = 2 Y = {1, 3} A(3) = (1,3) δ(5) = 2 Y = {1, 3, 5} A(5) = (3,5) δ(7) = 2 δ=2 Y = {1, 3, 5, 7} A(7) = (5,7) f(5,7) = 7 f(3,5) = 7 f(1,3) = 10 f(7,1) = 30 49 Problema do Fluxo Máximo Exemplo: 20 2 20 5 5 7 10 10 6 4 5 12 1 15 15 8 9 4 15 7 7 8 6 8 3 15 8 8 8 12 8 30 ∞ δ(1) = +∞ δ = 0, P ∉ Y Y = {1} FIM 50 Problema do Fluxo Máximo Teorema do Corte Mínimo • Um conjunto de arcos C é chamado de corte separando P de S se ∃ Y ⊂ X com S ∈ Y e P ∉ Y tal que C = { u ∈ U: I(u) ∈ Y, T(u) ∉ Y } • Um corte separando P de S corta qualquer caminho de S a P no grafo G = (X,U). • Capacidade de um corte separando P de S: c(C) = ∑u∈C c(u) 51 Problema do Fluxo Máximo " Teorema: fluxo viável f corte C f(P,S) ≤ c(C) Y Y fS S fP S P f sp = f ps + f (P , S ) P f ps ≥ 0 ⇒ f (P , S ) ≤ f sp = f (u ) ∑ u C ∈ ≤ c (u ) = c (C ) ∑ u C ∈ 52 Problema do Fluxo Máximo • Corolário: Quando o algoritmo de rotulação termina com um fluxo f sem que seja possível marcar o nó P, f é a solução ótima do problema de fluxo máximo de S a P. u Y T(u) Y Y Y f(u) = c(u), senão a extremidade u estaria marcada I(u) u P∉Y f(u) = 0, senão a extremidade u estaria marcada 53 Problema do Fluxo Máximo • Corolário: Se as capacidades são inteiras, então o algoritmo de Ford e Fulkerson obtém em um número finito de iterações uma solução ótima do problema de fluxo máximo. 54 Problema do Fluxo Máximo • Teorema: O valor do fluxo máximo é igual à capacidade do corte mínimo separando P de S. Ao final do procedimento de rotulação: Y Y fSP = fPS + f*(P,S) fSP S fPS = 0 P fPS fSP = c(C) f*(P,S) = c(C) f(P,S) ≤ c(C) f*(P,S) corte é mínimo. 55 Problema do Fluxo Máximo Exemplo: 20 2 20 5 5 7 10 10 15 8 9 4 15 7 7 8 6 8 3 6 4 5 12 1 15 15 8 8 8 12 8 30 ∞ Corte mínimo Capacidade = 30 Fluxo máximo = 30 δ(1) = +∞ Y = {1} δ = 0, P ∉ Y FIM 56 ÁRVORES PROGRAMAÇÃO GERADORAS DE TRIPULAÇÕES MÍNIMAS Introdução • Árvore Geradora Mínima – AGM (Minimum Spanning Tree – MST) • Um dos problemas de otimização mais simples e mais bem estudados em Ciência da Computação e Teoria dos Grafos • Objetivos • Obtenção de uma árvore em um grafo conexo, com arestas valoradas, de tal forma que a soma dos custos das arestas seja mínimo Principais Algoritmos • Algoritmo de Boruvka (1926) O. Boruvka. O jistém problému minimálním. Práca Moravské Prirodovedecké Spolecnosi, 3 (1926), 37-58. (In Czech.) • Algoritmo de Kruskal (1956) J.B. Kruskal. On the shortest spanning tree of a graph and the traveling salesman problem. Proceedings of the American Mathematical Society, 7:48-50, 1956. • Algoritmo de Prim (1957) R.C. Prim. Shortest connection networks and some generalizations. Bell Systems Technology Journal, 36:1389-1401, 1957. ÁRVORES GERADORAS MÍNIMAS PROGRAMAÇÃO ALGORITMO DE BORUVKA DE TRIPULAÇÕES Algoritmo de Boruvka • Primeiro algoritmo proposto para resolução do Problema da Árvore Geradora Mínima • Surgiu em 1926 antes dos primeiros computadores e da publicação do primeiro livro sobre teoria dos grafos (1936) • Seu propósito era fornecer uma cobertura elétrica eficiente para a cidade de Bohemia • Método ideal para implementação em computadores paralelos ∈ Algoritmo de Boruvka • Seja um grafo G(N, A), onde N é o conjunto de nós e A o conjunto de arestas Passo 1: Para cada i ∈ N faça Ni ← { i } Passo 2: T* ← {} Passo 3: Enquanto |T*| < (n-1) faça Ø Para cada árvore Nk faça min(Nk, ik, jk) Ø Para cada árvore Nk faça Se os nós ik e jk pertencem a árvores diferentes então unir(ik, jk) e atualizar T* ← T* ∪ {(ik, jk)} Algoritmo de Boruvka 21 7 14 30 6 1 10 4 9 ÁRVORES GERADORAS MÍNIMAS PROGRAMAÇÃO ALGORITMO DE KRUSKAL DE TRIPULAÇÕES Algoritmo de Kruskal • Idéia do algoritmo: • Aresta de menor peso sempre pertence à árvore geradora de peso mínimo • Complexidade: O(A * log A) • Gargalo: ordenação das arestas Algoritmo de Kruskal Criar uma lista L com as arestas ordenadas em ordem crescente de pesos. Criar |V| subárvores contendo cada uma um nó isolado. F ← ∅ contador ← 0 Enquanto contador < |V|-1 e L ≠ ∅ faça Seja (u,v) o próximo arco de L. L ← L – {(u,v)} Se u e v não estão na mesma subárvore então F ← F ∪ {(u,v)} Unir as subárvores que contêm u e v. contador ← contador + 1 fim-se fim-enquanto Algoritmo de Kruskal 3 17 7 2 7 11 8 9 12 10 Variação do Algoritmo de Kruskal • Idéia do algoritmo: • Se a aresta de menor peso sempre pertence à árvore geradora de peso mínimo, então a aresta de maior peso não pertence, se o número de arestas for maior que n-1 • Complexidade: O(A*log A) • Gargalo: ordenação das arestas Variação do Algoritmo de Kruskal Criar uma lista L com as arestas ordenadas em ordem decrescente de pesos. F ← L contador ← 0 Enquanto contador < |A|-|V|-1 e L ≠ ∅ faça Seja (u,v) o próximo arco de L. L ← L – {(u,v)} Se (u,v) não é ponte então F ← F - {(u,v)} contador ← contador + 1 fim-se fim-enquanto Variação do Algoritmo de Kruskal 3 17 7 2 7 11 8 9 12 10 Algoritmo de Kruskal • Principais desvantagens: • O método exige uma “etapa preparação”, por exemplo, em caso de representação por listas de adjacência • Grande consumo de memória ÁRVORES GERADORAS MÍNIMAS PROGRAMAÇÃO ALGORITMO DE PRIM DE TRIPULAÇÕES Algoritmo de Prim • Idéia do algoritmo: • Inicia com uma árvore formada apenas por um nó qualquer do grafo, ou pela aresta de peso mínimo. • A cada iteração, adiciona a aresta de menor peso que conecta um nó já conectado a um nó ainda não conectado • Complexidade: O(A*log N) = O(A*log A) • Usando Heap de Fibonacci: O(A + N*log N) Algoritmo de Prim Seja (u,v) a aresta de menor peso. F ← {(u,v)} Para i = 1,...,n faça Se c(i,u) < c(i,v) então prox(i) ← u Senão prox(i) ← v fim-para prox(u), prox(v) ← 0, contador ← 0 Enquanto contador < n-2 faça Seja j tal que prox(j)≠0 e c(j,prox(j)) é mínimo. F ← F ∪ {(j,prox(j))} prox(j) ← 0 Para i = 1,...,n faça Se prox(i) ≠ 0 e c(i,prox(i)) > c(i,j) então prox(i) ← j fim-para contador ← contador + 1 fim-enquanto Algoritmo de Prim 3 17 7 2 7 11 8 9 12 10 ÁRVORES GERADORAS MÍNIMAS PROGRAMAÇÃO OTIMIZAÇÕES DE TRIPULAÇÕES Implementações • Variação na estrutura de dados utilizada: • Prim usando Pairing Heap • Prim usando Fibonacci Heap • Prim usando Binary Heap Pairing Heap x Fibonacci Heap Complexidade Amortizada Complex. “Real” Pairing Heap Fibonacci Heap isEmpty O(1) O(1) O(1) size O(1) O(1) O(1) getMax O(1) O(1) O(1) put O(1) O(log n) ** O(1) removeMax O(n) O(log n) O(log n) meld O(1) O(log n) ** O(1) remove O(n) O(log n) O(log n) increaseKey O(n) O(log n) ** O(1) Operação Resultados de Moret e Shapiro (1991) • Grafos esparsos 1) 2) 3) 4) 5) Binary Heap Fibonacci Heap Slay tree Rank-relaxed Heap Pairing Heap Resultados de Moret e Shapiro (1991) • Grafos com A = N * log N 1) 2) 3) 4) 5) Binary Heap Fibonacci Heap Slay tree Rank-relaxed Heap Pairing Heap Resultados de Moret e Shapiro (1991) • Grafos com A = N3/2 (grafos densos) 1) 2) 3) 4) 5) Binary Heap Fibonacci Heap Slay tree Rank-relaxed Heap Pairing Heap Resultados da Literatura • Moret e Shapiro (1991) fazem uma série de experimentos envolvendo vários algoritmos e estruturas de dados para gerar uma AGM. • Nos testes foram utilizadas diferentes estruturas e densidades de grafos • Foi feita uma análise tanto de desempenho quanto de consumo de espaço em memória Resultados da Literatura • Consumo de memória Resultados da Literatura • Tempo de execução Perguntas? 85