Algoritmo de Kruskal
Disciplina Análise de Algoritmos
Bacharelado em CC
Algoritmo de Kruskal
Utiliza o arcabouço geral do método guloso para MST, com os
seguintes detalhes:
• O conjunto inicial X0 é um subgrafo com |V| vértices isolados e
nenhuma aresta.
• A cada etapa k :
– O corte (S,V-S) só deve satisfazer a propriedade de “respeitar” o
Xk-1, isto é, cada aresta de Xk-1 tem seus dois vértices do mesmo
lado do corte. Nenhuma aresta de Xk-1 atravessa o corte.
– Não necessariamente um lado do corte contém TODAS as
arestas de Xk-1, como no algoritmo PRIM.
Exemplo de Aplicação de Kruskal
Considere o seguinte grafo G
Etapa 0 : X0 é o subgrafo X0 = (V,E) onde V = {a,b,c,d,e,f,g,h,i} e E = 
Lembre que : No algoritmo de PRIM, na etapa 0, X0 = (V,E), onde V = , E = 
Etapa 1
Considera a aresta de menor custo {h,g} ligando duas
componentes conexas h e g distintas !
X1 = {h-g}
Etapa 2
X1 = {h-g}
Considera a 2a aresta de menor custo {i,c} – ligando
duas componentes conexas distintas i e c
X2 = {h-g,i-c}
Etapa 3
X2 = {h-g,i-c}
Considera a 3a aresta de menor custo {g,f} – ligando
duas componentes conexas distintas {h-g} e {f}
X3 = {h-g,i-c,g-f}
Etapa 4
X3 = {h-g,i-c,g-f}
Considera a 4a aresta de menor custo {a,b}, ligando as
componentes conexas distintas {a} e {b}
X4 = {h-g,i-c,g-f,a-b}
Etapa 5
X4 = {h-g,i-c,g-f,a-b}
Considera a 5a aresta de menor custo {c,f}, ligando duas
componentes conexas distintas
X5 = {h-g,i-c,g-f,a-b,c-f}
Etapa 6
X5 = {h-g,i-c,g-f,a-b,c-f}
Considera a 6a aresta de menor custo {c,d} ligando duas
componentes conexas distintas.
Repare que a aresta i-g liga vértices da mesma componente
conexa de X6, logo não pode ser considerada, embora seja
de menor custo !
Resultado final
Exercicio: continue as demais etapas a partir da sétima até chegar
neste resultado final.
Justificando a corretude do
Algoritmo de Kruskal
Considere o seguinte grafo G
Etapa 0 : X0 é o subgrafo X0 = (V,E) onde V = {a,b,c,d,e,f,g,h,i} e E = 
Corte S = { } , V – S = V
Lembre que : No algoritmo de PRIM, na etapa 0, X0 = (V,E), onde V = , E = 
Etapa 1
Considera a aresta de menor custo {h,g}
Corte: S = {h}, V- S = {a,b,c,d,e,f,g,i}
S contém os vértices das arestas de X0
(nenhum vértice !)
X1 = {h-g}
Etapa 2
X1 = {h-g}
Considera a 2a aresta de menor custo {i,c}
Corte: S = {h,g,i}, S contém os vértices das arestas de X1
X2 = {h-g,i-c}
Etapa 3
X2 = {h-g,i-c}
Considera a 3a aresta de menor custo {g,f}
Corte: S = {h,g} V- S = {i,c,d,e,f,a,b}, cada aresta de X2
está contida em S ou em V-S.
X3 = {h-g,i-c,g-f}
Etapa 4
X3 = {h-g,i-c,g-f}
Considera a 4a aresta de menor custo {a,b}
Corte: S = {h,g,f,a} V- S = {i,c,d,e,b}, cada aresta de X3 está
contida em S ou em V-S.
X4 = {h-g,i-c,g-f,a-b}
Etapa 5
X4 = {h-g,i-c,g-f,a-b}
Considera a 5a aresta de menor custo {c,f}
Corte: S = {h,g,f,a,b}, V- S = {i,c,d,e}
X5 = {h-g,i-c,g-f,a-b,c-f}
Etapa 6
X5 = {h-g,i-c,g-f,a-b,c-f}
Considera a 6a aresta de menor custo {c,d}
Corte: S = {h,g,i,c,a,b,f}, V-S = {d,e}
X6 = {h-g,i-c,g-f,a-b,c-f,c-d}
Repare que a aresta i-g liga vértices da mesma componente
conexa de X6, logo não pode ser considerada, embora seja de
menor custo !
Algoritmo de Kruskal
1. X = grafo (V,)
2. Para cada vértice v ∈ V
3. Makeset(v) ; % transforma cada vértice isolado é
uma componente conexa de X
4. Ordena as arestas de G em ordem crescente de custo
5. Para cada aresta (u,v) de G, considerando a ordem
crescente de custo
6. Se Find(u)  Find(v) % no máximo |V| - 1 vezes
7. X = X  {(u,v)}
8. Union(Find(u), Find(v)
9. Retorna X
Esquema Geral:
|V|.makeset + O(|E|.log(|E|) + |E|.(Find) + (|V| - 1) (Union)
Análise da Complexidade
Esquema Geral:
|V|.makeset + O(|E|.log(|E|) + |E|.(Find) + (|V| - 1) (Union)
A complexidade depende da implementação das operações de
conjunto:
Makeset, Find, Union
Implementação de Find e Union utilizando representação de
conjuntos por árvores e ranks em cada nó da árvore : log(|V|)
Complexidade = |V|.O(1)+ O(|E|.log(|E|) + O(|E|+|V|).(log(|V|))
Pior caso |E| = |V|2 : O( log(|E|) = O( log(|V) )
Complexidade = O( |V|2 log(|V| )
Ver prova nos slides
seguintes
Representação de conjuntos como
àrvores
Como representar um conjunto {A1,..., An} por uma árvore ?
Exemplo: {A,B,C,D,E,F,G}
Passo 0: Constrói, para cada elemento X, uma árvore de um único elemento
(raiz) X0 de rank 0.
A0
B0
C0
D0
E0
F0
G0
Passos 1, 2 e 3: union(A,B), union(C,D), union(E,F), resultando em 4 árvores:
B1
D1
F1
A0
C0
E0
union(A,B)
union(C,D)
union(E,F)
G0
• Passos 4 e 5: union(B,D), union(F,G) : resultado 2 árvores
D2
F1
B1
E0
C0
G0
A0
union(B,D)
union(F,G)
Passo 6 : union(D,F)
D2
B1
C0
F1
A0
E0
Representação de {A,B,C,D,E,F,G} em árvore
G0
Representantes de Conjuntos
• O representante oficial de uma árvore é a sua raiz.
• Assim, a árvore
D2
B1
C0
A0
tem como representante oficial a raiz D.
Também pode-se se referir a esta árvore através de qualquer de seus nós. Por
exemplo, a árvore da figura pode ser referida por “A”. Mas seu representante
oficial é D.
Operação Find(A): retorna o representante oficial da árvore contendo o nó A = D
Se rank D é k então Find(A) executa no máximo k passos para chegar até a raiz D.
Operações Find e Makeset
Makeset(x)
1.
pai(x) = x
2.
rank(x) = 0
Complexidade de Makeset = O(1)
Find(x)
1.
While x  pai(x)
2.
x = pai(x)
3.
Retorna x
Complexidade de Find(x) = O(k), onde k = profundidade da árvore contendo x
= rank da raiz desta árvore
Observação: a raiz de uma árvore é o único nó que é seu próprio pai.
Operação Union
Union(x,y)
1.
2.
3.
4.
5.
6.
7.
8.
9.
Rx = Find(x)
Ry = Find(y)
Se Rx = Ry: retorna x
Se rank(Rx) > rank(Ry)
pai(Ry) = Rx
Else
Pai(Rx) = Ry
Se rank(Rx) = rank(Ry)
rank(Ry) = Rank(Ry) + 1
Complexidade das operações Find
e Union
Qual a relação entre o número n de elementos de uma árvore e a sua
profundidade k ?
Vamos mostrar k ≤ log2(n)
Propriedade 1: Para todo x (diferente da raiz), rank(x) < rank(pai(x))
Propriedade 2: Qualquer nó de rank k tem no mínimo 2k descendentes.
Prova: por indução sobre k
Base da indução: k = 0. Neste caso o único descendente é o próprio nó. Portanto
número de descendentes = 1 = 20
Passo da indução: Suponha o resultado verdadeiro para rank = k-1 e seja x um
nó de rank k > 0. Neste caso, a árvore de x foi obtida juntando-se duas árvores
de raiz u e raiz v de mesmo rank k-1. Logo o número de descendentes de x =
número de descendentes de u + número de descendentes de v ≤ 2k-1 + 2k-1 = 2.
2k-1 = 2k
Complexidade das operações Find
e Union
Qual a relação entre o número n de elementos de uma árvore e a sua
profundidade k ?
Considere uma árvore de n elementos com raiz x de rank k
Então k = profundidade da árvore
Pela propriedade 2, temos que n ≥ 2k
Logo: log2(n) ≥ k
Portanto : k ≤ log2(n)
Portanto a complexidade de Find e Union é O(log(n)), uma vez que todas as
árvores têm profundidade máxima log2(n)
Download

Algoritmo de Kruskal