Análise e Síntese de Algoritmos
Contexto
• Algoritmos Elementares em Grafos
(
CLR, Cap. 22)
– BFS & DFS– Ordenação Topológica & SCCs
• Árvores Abrangentes de Menor Custo (
CLR, Cap. 23)
– Algoritmos de Borůvka, Kruskal e Prim• Caminhos mais curtos com fonte única (
CLR, Cap. 24)
– Algoritmos de Dijkstra e Bellman-Ford• Caminhos mais curtos entre todos os pares (
CLR, Cap. 25)
– Solução Recursiva e Algoritmo de Floyd-WarshallResumo
• Caminhos Mais Curtos entre Todos os Pares (APSPs)
– Definições
– Soluções recursivas
• Algoritmo de Floyd-Warshall – Fecho Transitivo
Caminhos Mais Curtos entre Todos
os Pares (APSPs) — Observações
• Encontrar caminhos mais curtos entre todos os pares
de vértices
• Se
pesos não negativos
– Utilizar algoritmo de Dijkstra, assumindo cada vértice como fonte: O(V E lg V) (que é O(V3 lg V) se grafo é denso)
• Se
pesos negativos
– Utilizar algoritmo de Bellman-Ford, assumindo cada vértice como fonte: O(V2E) (que é O(V4) se grafo é denso)
APSPs — Definições
• Representação: utilização de
matriz de adjacências
• Pesos dos arcos: matriz
(n x n) W = (w
ij)
• Representação dos caminhos mais curtos:
matriz (n x n)
D = (d
ij)
– dij é o peso do caminho mais curto entre os vértices i e j • dij = δ(vi,vj)
( )
( )
∉ ≠ ∞ ∈ ≠ = = E j ,i e j i se E j ,i e j i se j) (i, arco do peso j i se 0 wijAPSPs — Definições
• Representação de caminhos mais curtos
– Matriz de predecessores ∏ = (πij)
– πij:
• NIL: se i = j ou não existe caminho de i para j
• Caso contrário: predecessor de j num caminho mais curto de i para j
– Sub-grafo de predecessores de G para i, Gπ, i = (Vπ, i, Eπ, i)
• Sub-grafo induzido pela linha i de ∏
– Exemplo
{
j V : NIL}
{}
i Vπi, = ∈ πij ≠ ∪( )
{
,j : j V {i}}
Eπi, = πij ∈ πi, −APSPs — Solução Recursiva
• Sub-caminhos de caminhos mais curtos são também
caminhos mais curtos
• Peso mínimo em caminho de vértice i para vértice j
que contém não mais do que
m arcos
:
– Com m = 0, existe caminho de i para j se e só se i = j
– Para m ≥ 1, ) m ( ij d ( )
{
( ){
( )}
}
{
( )}
kj 1 m ik n k 1 kj 1 m ik n k 1 1 m ij mij min d ,min d w min d w
d = + = − + ≤ ≤ − ≤ ≤ − ( ) ≠ ∞ = = j i se j i se 0 d 0 ij w = 0
APSPs — Solução Recursiva
• Calcular sequência de matrizes D
(1), …, D
(n-1), onde
– D(n-1) contém os pesos dos caminhos mais curtos – D(1) = W
• Complexidade:
Θ(n
3) p/ cada matriz; Total:
Θ(n
4)
Extend-Shortest-Paths(D,W) n = rows[W] D’: matriz (n x n) for i = 1 to n for j = 1 to n for k = 1 to n return D’
(
ik kj)
' ij ' ij min d ,d w d = + ∞ = ' ij dAPSPs — Solução Recursiva
• Genericamente: calcular D
(i)em função de D
(i-1)(e de W)
• Complexidade para cálculo de D
(n):
Θ(n
4)
• OBS: é possível melhorar complexidade reduzindo
número de matrizes calculadas:
Θ(n
3lg n)
APSPs — Algoritmo de Floyd-Warshall
• Caracterização de um caminho mais curto
– Vértices intermédios de caminho p = 〈v1,v2,…,vk〉, {v2,…,vk-1}
• Considerar todos os caminhos entre i e j com
vértices intermédios retirados do conjunto {1,
…,k} e
seja p um caminho mais curto (
p é simples
)
– Se k não é vértice intermédio de p, então todos os vértices intermédios de p estão em {1,…,k-1}
– Se k é vértice intermédio de p, então existem caminhos p1 e p2, respectivamente de i para k e de k para j com vértices intermédios em {1,…,k}
• k não é vértice intermédio de p1 e de p2
APSPs — Algoritmo de Floyd-Warshall
• Formulação
i j k p1 p2 Vértices entre 1 e k-1 ( ) ( ) ( ) ( )(
)
≥ + = = − − − 1 k se d d , d min 0 k se w d k 1 kj 1 k ik 1 k ij ij k ij Vértices entre 1 e kAPSPs — Algoritmo de Floyd-Warshall
Floyd-Warshall(W) n = rows[W] D(0) = W for k = 1 to n for i = 1 to n for j = 1 to n return D(n) ( )(
( ) ( ) (k 1))
kj 1 k ik 1 k ij k ij min d ,d d d = − − + −• Complexidade:
Θ(n
3)
• Exemplo
Fecho Transitivo de um Grafo Dirigido
• Dado um grafo G = (V, E) dirigido, o
fecho transitivo
é definido por G* = (V, E*) tal que,
E*={(i, j): existe caminho de i para j em G}
• Algoritmo:
– Atribuir a cada arco peso 1 e utilizar algoritmo de Floyd-Warshall
• Se dij ≠ ∞, então (i, j) ∈ E* • Complexidade: Θ(n3)
Fecho Transitivo de um Grafo Dirigido
• Outro algoritmo:
– Substituir operações min e + por ∨ e ∧, respectivamente – Se existe caminho de i para j com todos os vértices
intermédios em {1,2,…,k}, – Caso contrário,
– Formulação:
– Complexidade: Θ(n3) (mas constantes menores) – Exemplo ( ) 1 t k ij = ( ) 0 t k ij = ( ) t( )
(
t( ) t( ))
sek 1 t k 1 kj 1 k ik 1 k ij k ij = − ∨ − ∧ − ≥ ( )( )
( )
∈ = ∉ ≠ = E j ,i ou j i se 1 E j ,i e j i se 0 t 0 ijFecho Transitivo de um Grafo Dirigido
Transitive-Closure(G) n = |V[G]| for i = 1 to n for j = 1 to n if i = j or (i, j) ∈ E else for k = 1 to n for i = 1 to n for j = 1 to n return T(n) ( ) ( )(
( ) (k 1))
kj 1 k ik 1 k ij k ij t t t t = − ∨ − ∧ − ( ) 1 t 0 ij = ( ) 0 t 0 ij =APSPs — Algoritmo de Johnson
• Utiliza algoritmos de Dijkstra e de Bellman-Ford
• Baseado em
re-pesagem dos arcos
– Se arcos com pesos não negativos, utilizar Dijkstra para cada vértice
– Caso contrário, calcular novo conjunto de pesos não negativos w’, tal que
• Um caminho mais curto de u para v com função w é também caminho mais curto com função w’
APSPs — Algoritmo de Johnson
• Dado G = (V, E), com função de pesos w e de
re-pesagem h: V
→ R, seja
w’(u, v) = w(u, v) + h(u) - h(v)
• Seja p =
〈v
0,v
1,
…,v
k〉. Então
w(p) =
δ(v
0, v
k) se e só se
w’(p) =
δ’(v
0, v
k)
=
δ(v
0, v
k) + h(v
0) - h(v
k)
– Existe ciclo negativo com w se e só se existe ciclo negativo com w’
( )
p w( ) ( ) ( )
p h v0 h vk ' w = + −( )
(
)
(
) ( ) ( )
(
)
(
) ( ) ( )
( ) ( ) ( )
k k 1 i i 1 i i 1 i k 1 i i 1 i v h v h v , v w v , v ' w p ' w − + = =∑
∑
∑
= − − = −APSPs — Algoritmo de Johnson
( ) (
p v0,vk)
w'( )
p '(
v0,vk)
w = δ ⇒ = δ
Hipótese: existe pz, caminho mais curto de v0 para vk com w’ Então: w'
( )
pz < w'( )
p( ) ( ) ( )
pz h v0 h vk w'( )
pz w'( )
p w( ) ( ) ( )
p h v0 h vk w + − = < = + −( )
pz < w( )
p w O que implicaMas p é caminho mais curto com w; contradição !
OBS: Para quaisquer caminhos p1, p2 entre v0 e vk, verifica-se
APSPs — Algoritmo de Johnson
( ) (
p v0,vk)
w'( )
p '(
v0,vk)
w = δ ⇐ = δ
Semelhante:
Admitir pz como caminho mais curto de v0 para vk com w (ou considerar observação anterior)
Existe ciclo negativo com w se e só se existe com w’
( )
c 0 w ; v v ; v , , v , v c = 〈 0 1 K k〉 0 = k <( )
c w( ) ( ) ( )
c h v h v w( )
c ' w = + 0 − k =∴Caminhos mais curtos e ciclos negativos
APSPs — Algoritmo de Johnson
• Dado G = (V, E), criar G’ = (V’,E’):
– V’ = V ∪ { s }
– E’ = E ∪ { (s, v) : v ∈ V } (∀ v ∈ V, atingível a partir de s) – w(s, v) = 0
• Com ciclos negativos:
– Detectados com algoritmo de Bellman-Ford aplicado a G’ !
• Sem ciclos negativos:
– Definir: h(v) = δ(s, v)
– Dado que: h(v) ≤ h(u) + w(u, v)
APSPs — Algoritmo de Johnson
• Executar Dijkstra para todo o u
∈ V
– Cálculo de δ’(u,v), para u ∈ V – Mas também,
• δ’(u,v) = δ(u, v) + h(u) - h(v)
APSPs — Algoritmo de Johnson
Johnson(G)Representar G’
if Bellman-Ford(G’,w,s) = FALSE print “Indicar ciclo negativo” else
atribuir h(v) = δ(s, v), calculado com Bellman-Ford
calcular w’(u,v) = w(u,v) + h(u) - h(v) para cada arco (u,v)
foreach v ∈ V[G]
executar Dijkstra(G,w’,v); calcular δ’(u, v)
duv = δ’(u, v) + h(v) - h(u)
APSPs — Algoritmo de Johnson
• Complexidade:
– Bellman-Ford: O(V E)
– Executar Dijkstra para cada vértice: O(V (V + E) lg V) • Assumindo amontoado (heap) binário
– Total: O(V (V + E) lg V)
• Útil para grafos esparsos
• Exemplo
Revisão
• Caminhos Mais Curtos entre Todos os Pares (APSPs)
– Definições – Solução recursiva – Algoritmo de Floyd-Warshall – Fecho Transitivo – Algoritmo de Johnson