In [ ]:
import sys
sys.path.append('..')
import socnet as sn
A seguir, vamos configurar as propriedades visuais:
In [ ]:
sn.graph_width = 320
sn.graph_height = 180
Por fim, vamos carregar e visualizar um grafo:
In [ ]:
g = sn.load_graph('5-kruskal.gml', has_pos=True)
for e in g.edges_iter():
g.edge[e[0]][e[1]]['label'] = g.edge[e[0]][e[1]]['c']
sn.show_graph(g, elab=True)
Dizemos que:
O custo de uma árvore geradora $T$ é
$\sum_{\{n, m\} \in T} c(n, m)$.
Uma árvore geradora é mínima se não existe outra árvore geradora de custo menor. Note que podem existir múltiplas árvores geradoras mínimas.
Podemos eficientemente obter uma árvore geradora mínima usando o algoritmo de Kruskal. A ideia desse algoritmo é simples: inicializamos uma floresta $F$ como o conjunto vazio e verificamos todas as arestas em ordem não-decrescente de custo. Para cada aresta, adicionamos ela a $F$ se essa adição não formar circuito no grafo $(N, F)$.
Vamos especificar uma classe que representa a floresta. Não é necessário entender todos os detalhes dela, apenas que o atributo f é o conjunto das arestas e os dois últimos métodos são auto-explicativos.
In [ ]:
class Forest(object):
def __init__(self, g):
self.g = g
self.f = set()
for n in g.nodes():
self._make_set(n)
def _make_set(self, x):
g.node[x]['p'] = x
g.node[x]['rank'] = 0
def _union(self, x, y):
self._link(self._find_set(x), self._find_set(y))
def _link(self, x, y):
if g.node[x]['rank'] > g.node[y]['rank']:
g.node[y]['p'] = x
else:
g.node[x]['p'] = y
if g.node[x]['rank'] == g.node[y]['rank']:
g.node[y]['rank'] = g.node[y]['rank'] + 1
def _find_set(self, x):
if x != g.node[x]['p']:
g.node[x]['p'] = self._find_set(g.node[x]['p'])
return g.node[x]['p']
def adding_does_not_form_circuit(self, n, m):
return self._find_set(n) != self._find_set(m)
def add(self, n, m):
self.f.add((n, m))
self._union(n, m)
In [ ]:
# sua resposta