| 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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
 | // Copyright 2014 Sonia Keys
// License MIT: http://opensource.org/licenses/MIT
package graph
import (
	"container/heap"
	"sort"
)
type dsElement struct {
	from NI
	rank int
}
type disjointSet struct {
	set []dsElement
}
func newDisjointSet(n int) disjointSet {
	set := make([]dsElement, n)
	for i := range set {
		set[i].from = -1
	}
	return disjointSet{set}
}
// return true if disjoint trees were combined.
// false if x and y were already in the same tree.
func (ds disjointSet) union(x, y NI) bool {
	xr := ds.find(x)
	yr := ds.find(y)
	if xr == yr {
		return false
	}
	switch xe, ye := &ds.set[xr], &ds.set[yr]; {
	case xe.rank < ye.rank:
		xe.from = yr
	case xe.rank == ye.rank:
		xe.rank++
		fallthrough
	default:
		ye.from = xr
	}
	return true
}
func (ds disjointSet) find(n NI) NI {
	// fast paths for n == root or from root.
	// no updates need in these cases.
	s := ds.set
	fr := s[n].from
	if fr < 0 { // n is root
		return n
	}
	n, fr = fr, s[fr].from
	if fr < 0 { // n is from root
		return n
	}
	// otherwise updates needed.
	// two iterative passes (rather than recursion or stack)
	// pass 1: find root
	r := fr
	for {
		f := s[r].from
		if f < 0 {
			break
		}
		r = f
	}
	// pass 2: update froms
	for {
		s[n].from = r
		if fr == r {
			return r
		}
		n = fr
		fr = s[n].from
	}
}
// Kruskal implements Kruskal's algorithm for constructing a minimum spanning
// forest on an undirected graph.
//
// While the input graph is interpreted as undirected, the receiver edge list
// does not actually need to contain reciprocal arcs.  A property of the
// algorithm is that arc direction is ignored.  Thus only a single arc out of
// a reciprocal pair must be present in the edge list.  Reciprocal arcs (and
// parallel arcs) are allowed though, and do not affect the result.
//
// The forest is returned as an undirected graph.
//
// Also returned is a total distance for the returned forest.
//
// The edge list of the receiver is sorted as a side effect of this method.
// See KruskalSorted for a version that relies on the edge list being already
// sorted.
func (l WeightedEdgeList) Kruskal() (g LabeledUndirected, dist float64) {
	sort.Sort(l)
	return l.KruskalSorted()
}
// KruskalSorted implements Kruskal's algorithm for constructing a minimum
// spanning tree on an undirected graph.
//
// While the input graph is interpreted as undirected, the receiver edge list
// does not actually need to contain reciprocal arcs.  A property of the
// algorithm is that arc direction is ignored.  Thus only a single arc out of
// a reciprocal pair must be present in the edge list.  Reciprocal arcs (and
// parallel arcs) are allowed though, and do not affect the result.
//
// When called, the edge list of the receiver must be already sorted by weight.
// See Kruskal for a version that accepts an unsorted edge list.
//
// The forest is returned as an undirected graph.
//
// Also returned is a total distance for the returned forest.
func (l WeightedEdgeList) KruskalSorted() (g LabeledUndirected, dist float64) {
	ds := newDisjointSet(l.Order)
	g.LabeledAdjacencyList = make(LabeledAdjacencyList, l.Order)
	for _, e := range l.Edges {
		if ds.union(e.N1, e.N2) {
			g.AddEdge(Edge{e.N1, e.N2}, e.LI)
			dist += l.WeightFunc(e.LI)
		}
	}
	return
}
// Prim implements the Jarník-Prim-Dijkstra algorithm for constructing
// a minimum spanning tree on an undirected graph.
//
// Prim computes a minimal spanning tree on the connected component containing
// the given start node.  The tree is returned in FromList f.  Argument f
// cannot be a nil pointer although it can point to a zero value FromList.
//
// If the passed FromList.Paths has the len of g though, it will be reused.
// In the case of a graph with multiple connected components, this allows a
// spanning forest to be accumulated by calling Prim successively on
// representative nodes of the components.  In this case if leaves for
// individual trees are of interest, pass a non-nil zero-value for the argument
// componentLeaves and it will be populated with leaves for the single tree
// spanned by the call.
//
// If argument labels is non-nil, it must have the same length as g and will
// be populated with labels corresponding to the edges of the tree.
//
// Returned are the number of nodes spanned for the single tree (which will be
// the order of the connected component) and the total spanned distance for the
// single tree.
func (g LabeledUndirected) Prim(start NI, w WeightFunc, f *FromList, labels []LI, componentLeaves *Bits) (numSpanned int, dist float64) {
	al := g.LabeledAdjacencyList
	if len(f.Paths) != len(al) {
		*f = NewFromList(len(al))
	}
	b := make([]prNode, len(al)) // "best"
	for n := range b {
		b[n].nx = NI(n)
		b[n].fx = -1
	}
	rp := f.Paths
	var frontier prHeap
	rp[start] = PathEnd{From: -1, Len: 1}
	numSpanned = 1
	fLeaves := &f.Leaves
	fLeaves.SetBit(start, 1)
	if componentLeaves != nil {
		componentLeaves.SetBit(start, 1)
	}
	for a := start; ; {
		for _, nb := range al[a] {
			if rp[nb.To].Len > 0 {
				continue // already in MST, no action
			}
			switch bp := &b[nb.To]; {
			case bp.fx == -1: // new node for frontier
				bp.from = fromHalf{From: a, Label: nb.Label}
				bp.wt = w(nb.Label)
				heap.Push(&frontier, bp)
			case w(nb.Label) < bp.wt: // better arc
				bp.from = fromHalf{From: a, Label: nb.Label}
				bp.wt = w(nb.Label)
				heap.Fix(&frontier, bp.fx)
			}
		}
		if len(frontier) == 0 {
			break // done
		}
		bp := heap.Pop(&frontier).(*prNode)
		a = bp.nx
		rp[a].Len = rp[bp.from.From].Len + 1
		rp[a].From = bp.from.From
		if len(labels) != 0 {
			labels[a] = bp.from.Label
		}
		dist += bp.wt
		fLeaves.SetBit(bp.from.From, 0)
		fLeaves.SetBit(a, 1)
		if componentLeaves != nil {
			componentLeaves.SetBit(bp.from.From, 0)
			componentLeaves.SetBit(a, 1)
		}
		numSpanned++
	}
	return
}
// fromHalf is a half arc, representing a labeled arc and the "neighbor" node
// that the arc originates from.
//
// (This used to be exported when there was a LabeledFromList.  Currently
// unexported now that it seems to have much more limited use.)
type fromHalf struct {
	From  NI
	Label LI
}
type prNode struct {
	nx   NI
	from fromHalf
	wt   float64 // p.Weight(from.Label)
	fx   int
}
type prHeap []*prNode
func (h prHeap) Len() int           { return len(h) }
func (h prHeap) Less(i, j int) bool { return h[i].wt < h[j].wt }
func (h prHeap) Swap(i, j int) {
	h[i], h[j] = h[j], h[i]
	h[i].fx = i
	h[j].fx = j
}
func (p *prHeap) Push(x interface{}) {
	nd := x.(*prNode)
	nd.fx = len(*p)
	*p = append(*p, nd)
}
func (p *prHeap) Pop() interface{} {
	r := *p
	last := len(r) - 1
	*p = r[:last]
	return r[last]
}
 |