-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathkruskals_algorithm.py
More file actions
69 lines (51 loc) · 1.82 KB
/
kruskals_algorithm.py
File metadata and controls
69 lines (51 loc) · 1.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
"""Kruskal's algorithm for minimum spanning tree (MST).
Given a weighted undirected graph, Kruskal's algorithm computes a minimum
spanning tree by considering the edges in nondecreasing order of weight and
adding an edge whenever it connects two previously disconnected components.
The graph is given as a list of edges of the form $(w, u, v)$, where $w$ is the
weight of the edge $uv$. Sorting this list yields the order in which edges are
considered. A Union Find data structure maintains the connected components.
Returns the edges of the MST together with its total weight.
Runs in $O(m \\log m)$ time, dominated by sorting the m edges.
"""
class Unionfind:
def __init__(self, size):
self._roots = list(range(size))
self._rank = [0] * size
def find(self, elt):
root = elt
while root != self._roots[root]:
root = self._roots[root]
while elt != root: # path compression
parent = self._roots[elt]
self._roots[elt] = root
elt = parent
return root
def __getitem__(self, elt):
return self.find(elt)
def is_connected(self, a, b):
return self.find(a) == self.find(b)
def union(self, a, b):
r1 = self.find(a)
r2 = self.find(b)
if r1 == r2:
return False
if self._rank[r1] < self._rank[r2]:
self._roots[r1] = r2
elif self._rank[r1] > self._rank[r2]:
self._roots[r2] = r1
else:
self._roots[r2] = r1
self._rank[r1] += 1
return True
def kruskal(n, edges):
uf = Unionfind(n)
mst = []
weight = 0
for w, u, v in sorted(edges):
if uf.union(u, v):
mst.append((u, v))
weight += w
if len(mst) == n - 1:
break
return mst, weight