-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathundir.go
817 lines (786 loc) · 23.1 KB
/
undir.go
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
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
// Copyright 2014 Sonia Keys
// License MIT: http://opensource.org/licenses/MIT
package graph
// undir.go has methods specific to undirected graphs, Undirected and
// LabeledUndirected.
import (
"fmt"
"github.com/soniakeys/bits"
)
// AddEdge adds an edge to a graph.
//
// It can be useful for constructing undirected graphs.
//
// When n1 and n2 are distinct, it adds the arc n1->n2 and the reciprocal
// n2->n1. When n1 and n2 are the same, it adds a single arc loop.
//
// The pointer receiver allows the method to expand the graph as needed
// to include the values n1 and n2. If n1 or n2 happen to be greater than
// len(*p) the method does not panic, but simply expands the graph.
//
// If you know or can compute the final graph order however, consider
// preallocating to avoid any overhead of expanding the graph.
// See second example, "More".
func (p *Undirected) AddEdge(n1, n2 NI) {
// Similar code in LabeledAdjacencyList.AddEdge.
// determine max of the two end points
max := n1
if n2 > max {
max = n2
}
// expand graph if needed, to include both
g := p.AdjacencyList
if int(max) >= len(g) {
p.AdjacencyList = make(AdjacencyList, max+1)
copy(p.AdjacencyList, g)
g = p.AdjacencyList
}
// create one half-arc,
g[n1] = append(g[n1], n2)
// and except for loops, create the reciprocal
if n1 != n2 {
g[n2] = append(g[n2], n1)
}
}
// RemoveEdge removes a single edge between nodes n1 and n2.
//
// It removes reciprocal arcs in the case of distinct n1 and n2 or removes
// a single arc loop in the case of n1 == n2.
//
// Returns true if the specified edge is found and successfully removed,
// false if the edge does not exist.
func (g Undirected) RemoveEdge(n1, n2 NI) (ok bool) {
ok, x1, x2 := g.HasEdge(n1, n2)
if !ok {
return
}
a := g.AdjacencyList
to := a[n1]
last := len(to) - 1
to[x1] = to[last]
a[n1] = to[:last]
if n1 == n2 {
return
}
to = a[n2]
last = len(to) - 1
to[x2] = to[last]
a[n2] = to[:last]
return
}
// ArcDensity returns density for a simple directed graph.
//
// Parameter n is order, or number of nodes of a simple directed graph.
// Parameter a is the arc size, or number of directed arcs.
//
// Returned density is the fraction `a` over the total possible number of arcs
// or a / (n * (n-1)).
//
// See also Density for density of a simple undirected graph.
//
// See also the corresponding methods AdjacencyList.ArcDensity and
// LabeledAdjacencyList.ArcDensity.
func ArcDensity(n, a int) float64 {
return float64(a) / (float64(n) * float64(n-1))
}
// Density returns density for a simple undirected graph.
//
// Parameter n is order, or number of nodes of a simple undirected graph.
// Parameter m is the size, or number of undirected edges.
//
// Returned density is the fraction m over the total possible number of edges
// or m / ((n * (n-1))/2).
//
// See also ArcDensity for simple directed graphs.
//
// See also the corresponding methods AdjacencyList.Density and
// LabeledAdjacencyList.Density.
func Density(n, m int) float64 {
return float64(m) * 2 / (float64(n) * float64(n-1))
}
// An EdgeVisitor is an argument to some traversal methods.
//
// Traversal methods call the visitor function for each edge visited.
// Argument e is the edge being visited.
type EdgeVisitor func(e Edge)
// Edges iterates over the edges of an undirected graph.
//
// Edge visitor v is called for each edge of the graph. That is, it is called
// once for each reciprocal arc pair and once for each loop.
//
// See also LabeledUndirected.Edges for a labeled version.
// See also Undirected.SimpleEdges for a version that emits only the simple
// subgraph.
func (g Undirected) Edges(v EdgeVisitor) {
a := g.AdjacencyList
unpaired := make(AdjacencyList, len(a))
for fr, to := range a {
arc: // for each arc in a
for _, to := range to {
if to == NI(fr) {
v(Edge{NI(fr), to}) // output loop
continue
}
// search unpaired arcs
ut := unpaired[to]
for i, u := range ut {
if u == NI(fr) { // found reciprocal
v(Edge{u, to}) // output edge
last := len(ut) - 1
ut[i] = ut[last]
unpaired[to] = ut[:last]
continue arc
}
}
// reciprocal not found
unpaired[fr] = append(unpaired[fr], to)
}
}
// undefined behavior is that unpaired arcs are silently ignored.
}
// FromList builds a forest with a tree spanning each connected component.
//
// For each component a root is chosen and spanning is done with the method
// Undirected.SpanTree, and so is breadth-first. Returned is a FromList with
// all spanned trees, a list of roots chosen, and a bool indicating if the
// receiver graph g was found to be a simple graph connected as a forest.
// Any cycles, loops, or parallel edges in any component will cause
// simpleForest to be false, but FromList f will still be populated with
// a valid and complete spanning forest.
func (g Undirected) FromList() (f FromList, roots []NI, simpleForest bool) {
p := make([]PathEnd, g.Order())
for i := range p {
p[i].From = -1
}
f.Paths = p
simpleForest = true
ts := 0
for n := range g.AdjacencyList {
if p[n].From >= 0 {
continue
}
roots = append(roots, NI(n))
ns, st := g.SpanTree(NI(n), &f)
if !st {
simpleForest = false
}
ts += ns
if ts == len(p) {
break
}
}
return
}
// HasEdge returns true if g has any edge between nodes n1 and n2.
//
// Also returned are indexes x1 and x2 such that g[n1][x1] == n2
// and g[n2][x2] == n1. If no edge between n1 and n2 is present HasArc
// returns `has` == false.
//
// See also HasArc. If you are interested only in the boolean result and
// g is a well formed (passes IsUndirected) then HasArc is an adequate test.
func (g Undirected) HasEdge(n1, n2 NI) (has bool, x1, x2 int) {
if has, x1 = g.HasArc(n1, n2); !has {
return has, x1, x1
}
has, x2 = g.HasArc(n2, n1)
return
}
// SimpleEdges iterates over the edges of the simple subgraph of an undirected
// graph.
//
// Edge visitor v is called for each pair of distinct nodes that is connected
// with an edge. That is, loops are ignored and parallel edges are reduced to
// a single edge.
//
// See also Undirected.Edges for a version that emits all edges.
func (g Undirected) SimpleEdges(v EdgeVisitor) {
for fr, to := range g.AdjacencyList {
e := bits.New(len(g.AdjacencyList))
for _, to := range to {
if to > NI(fr) && e.Bit(int(to)) == 0 {
e.SetBit(int(to), 1)
v(Edge{NI(fr), to})
}
}
}
// undefined behavior is that unpaired arcs may or may not be emitted.
}
// SpanTree builds a tree spanning a connected component.
//
// The component is spanned by breadth-first search from the given root.
// The resulting spanning tree in stored a FromList.
//
// If FromList.Paths is not the same length as g, it is allocated and
// initialized. This allows a zero value FromList to be passed as f.
// If FromList.Paths is the same length as g, it is used as is and is not
// reinitialized. This allows multiple trees to be spanned in the same
// FromList with successive calls.
//
// For nodes spanned, the Path member of the returned FromList is populated
// with both From and Len values. The MaxLen member will be updated but
// not Leaves.
//
// Returned is the number of nodes spanned, which will be the number of nodes
// in the component, and a bool indicating if the component was found to be a
// simply connected unrooted tree in the receiver graph g. Any cycles, loops,
// or parallel edges in the component will cause simpleTree to be false, but
// FromList f will still be populated with a valid and complete spanning tree.
func (g Undirected) SpanTree(root NI, f *FromList) (nSpanned int, simpleTree bool) {
a := g.AdjacencyList
p := f.Paths
if len(p) != len(a) {
p = make([]PathEnd, len(a))
for i := range p {
p[i].From = -1
}
f.Paths = p
}
simpleTree = true
p[root] = PathEnd{From: -1, Len: 1}
type arc struct {
from NI
half NI
}
var next []arc
frontier := []arc{{-1, root}}
for len(frontier) > 0 {
for _, fa := range frontier { // fa frontier arc
nSpanned++
l := p[fa.half].Len + 1
for _, to := range a[fa.half] {
if to == fa.from {
continue
}
if p[to].Len > 0 {
simpleTree = false
continue
}
p[to] = PathEnd{From: fa.half, Len: l}
if l > f.MaxLen {
f.MaxLen = l
}
next = append(next, arc{fa.half, to})
}
}
frontier, next = next, frontier[:0]
}
return
}
// TarjanBiconnectedComponents decomposes a graph into maximal biconnected
// components, components for which if any node were removed the component
// would remain connected.
//
// The receiver g must be a simple graph. The method calls the emit argument
// for each component identified, as long as emit returns true. If emit
// returns false, TarjanBiconnectedComponents returns immediately.
//
// See also the eqivalent labeled TarjanBiconnectedComponents.
func (g Undirected) TarjanBiconnectedComponents(emit func([]Edge) bool) {
// Implemented closely to pseudocode in "Depth-first search and linear
// graph algorithms", Robert Tarjan, SIAM J. Comput. Vol. 1, No. 2,
// June 1972.
//
// Note Tarjan's "adjacency structure" is graph.AdjacencyList,
// His "adjacency list" is an element of a graph.AdjacencyList, also
// termed a "to-list", "neighbor list", or "child list."
a := g.AdjacencyList
number := make([]int, len(a))
lowpt := make([]int, len(a))
var stack []Edge
var i int
var biconnect func(NI, NI) bool
biconnect = func(v, u NI) bool {
i++
number[v] = i
lowpt[v] = i
for _, w := range a[v] {
if number[w] == 0 {
stack = append(stack, Edge{v, w})
if !biconnect(w, v) {
return false
}
if lowpt[w] < lowpt[v] {
lowpt[v] = lowpt[w]
}
if lowpt[w] >= number[v] {
var bcc []Edge
top := len(stack) - 1
for number[stack[top].N1] >= number[w] {
bcc = append(bcc, stack[top])
stack = stack[:top]
top--
}
bcc = append(bcc, stack[top])
stack = stack[:top]
top--
if !emit(bcc) {
return false
}
}
} else if number[w] < number[v] && w != u {
stack = append(stack, Edge{v, w})
if number[w] < lowpt[v] {
lowpt[v] = number[w]
}
}
}
return true
}
for w := range a {
if number[w] == 0 && !biconnect(NI(w), -1) {
return
}
}
}
func (g Undirected) BlockCut(block func([]Edge) bool, cut func(NI) bool, isolated func(NI) bool) {
a := g.AdjacencyList
number := make([]int, len(a))
lowpt := make([]int, len(a))
var stack []Edge
var i, rc int
var biconnect func(NI, NI) bool
biconnect = func(v, u NI) bool {
i++
number[v] = i
lowpt[v] = i
for _, w := range a[v] {
if number[w] == 0 {
if u < 0 {
rc++
}
stack = append(stack, Edge{v, w})
if !biconnect(w, v) {
return false
}
if lowpt[w] < lowpt[v] {
lowpt[v] = lowpt[w]
}
if lowpt[w] >= number[v] {
if u >= 0 && !cut(v) {
return false
}
var bcc []Edge
top := len(stack) - 1
for number[stack[top].N1] >= number[w] {
bcc = append(bcc, stack[top])
stack = stack[:top]
top--
}
bcc = append(bcc, stack[top])
stack = stack[:top]
top--
if !block(bcc) {
return false
}
}
} else if number[w] < number[v] && w != u {
stack = append(stack, Edge{v, w})
if number[w] < lowpt[v] {
lowpt[v] = number[w]
}
}
}
if u < 0 && rc > 1 {
return cut(v)
}
return true
}
for w := range a {
if number[w] > 0 {
continue
}
if len(a[w]) == 0 {
if !isolated(NI(w)) {
return
}
continue
}
rc = 0
if !biconnect(NI(w), -1) {
return
}
}
}
// AddEdge adds an edge to a labeled graph.
//
// It can be useful for constructing undirected graphs.
//
// When n1 and n2 are distinct, it adds the arc n1->n2 and the reciprocal
// n2->n1. When n1 and n2 are the same, it adds a single arc loop.
//
// If the edge already exists in *p, a parallel edge is added.
//
// The pointer receiver allows the method to expand the graph as needed
// to include the values n1 and n2. If n1 or n2 happen to be greater than
// len(*p) the method does not panic, but simply expands the graph.
func (p *LabeledUndirected) AddEdge(e Edge, l LI) {
// Similar code in AdjacencyList.AddEdge.
// determine max of the two end points
max := e.N1
if e.N2 > max {
max = e.N2
}
// expand graph if needed, to include both
g := p.LabeledAdjacencyList
if max >= NI(len(g)) {
p.LabeledAdjacencyList = make(LabeledAdjacencyList, max+1)
copy(p.LabeledAdjacencyList, g)
g = p.LabeledAdjacencyList
}
// create one half-arc,
g[e.N1] = append(g[e.N1], Half{To: e.N2, Label: l})
// and except for loops, create the reciprocal
if e.N1 != e.N2 {
g[e.N2] = append(g[e.N2], Half{To: e.N1, Label: l})
}
}
// A LabeledEdgeVisitor is an argument to some traversal methods.
//
// Traversal methods call the visitor function for each edge visited.
// Argument e is the edge being visited.
type LabeledEdgeVisitor func(e LabeledEdge)
// Edges iterates over the edges of a labeled undirected graph.
//
// Edge visitor v is called for each edge of the graph. That is, it is called
// once for each reciprocal arc pair and once for each loop.
//
// See also Undirected.Edges for an unlabeled version.
// See also the more simplistic LabeledAdjacencyList.ArcsAsEdges.
func (g LabeledUndirected) Edges(v LabeledEdgeVisitor) {
// similar code in LabeledAdjacencyList.InUndirected
a := g.LabeledAdjacencyList
unpaired := make(LabeledAdjacencyList, len(a))
for fr, to := range a {
arc: // for each arc in a
for _, to := range to {
if to.To == NI(fr) {
v(LabeledEdge{Edge{NI(fr), to.To}, to.Label}) // output loop
continue
}
// search unpaired arcs
ut := unpaired[to.To]
for i, u := range ut {
if u.To == NI(fr) && u.Label == to.Label { // found reciprocal
v(LabeledEdge{Edge{NI(fr), to.To}, to.Label}) // output edge
last := len(ut) - 1
ut[i] = ut[last]
unpaired[to.To] = ut[:last]
continue arc
}
}
// reciprocal not found
unpaired[fr] = append(unpaired[fr], to)
}
}
}
// FromList builds a forest with a tree spanning each connected component in g.
//
// A root is chosen and spanning is done with the LabeledUndirected.SpanTree
// method, and so is breadth-first. Returned is a FromList with all spanned
// trees, labels corresponding to arcs in f,
// a list of roots chosen, and a bool indicating if the receiver graph g was
// found to be a simple graph connected as a forest. Any cycles, loops, or
// parallel edges in any component will cause simpleForest to be false, but
// FromList f will still be populated with a valid and complete spanning forest.
// FromList builds a forest with a tree spanning each connected component.
//
// For each component a root is chosen and spanning is done with the method
// Undirected.SpanTree, and so is breadth-first. Returned is a FromList with
// all spanned trees, labels corresponding to arcs in f, a list of roots
// chosen, and a bool indicating if the receiver graph g was found to be a
// simple graph connected as a forest. Any cycles, loops, or parallel edges
// in any component will cause simpleForest to be false, but FromList f will
// still be populated with a valid and complete spanning forest.
func (g LabeledUndirected) FromList() (f FromList, labels []LI, roots []NI, simpleForest bool) {
p := make([]PathEnd, g.Order())
for i := range p {
p[i].From = -1
}
f.Paths = p
labels = make([]LI, len(p))
simpleForest = true
ts := 0
for n := range g.LabeledAdjacencyList {
if p[n].From >= 0 {
continue
}
roots = append(roots, NI(n))
ns, st := g.SpanTree(NI(n), &f, labels)
if !st {
simpleForest = false
}
ts += ns
if ts == len(p) {
break
}
}
return
}
// SpanTree builds a tree spanning a connected component.
//
// The component is spanned by breadth-first search from the given root.
// The resulting spanning tree in stored a FromList, and arc labels optionally
// stored in a slice.
//
// If FromList.Paths is not the same length as g, it is allocated and
// initialized. This allows a zero value FromList to be passed as f.
// If FromList.Paths is the same length as g, it is used as is and is not
// reinitialized. This allows multiple trees to be spanned in the same
// FromList with successive calls.
//
// For nodes spanned, the Path member of returned FromList f is populated
// populated with both From and Len values. The MaxLen member will be
// updated but not Leaves.
//
// The labels slice will be populated only if it is same length as g.
// Nil can be passed for example if labels are not needed.
//
// Returned is the number of nodes spanned, which will be the number of nodes
// in the component, and a bool indicating if the component was found to be a
// simply connected unrooted tree in the receiver graph g. Any cycles, loops,
// or parallel edges in the component will cause simpleTree to be false, but
// FromList f will still be populated with a valid and complete spanning tree.
func (g LabeledUndirected) SpanTree(root NI, f *FromList, labels []LI) (nSpanned int, simple bool) {
a := g.LabeledAdjacencyList
p := f.Paths
if len(p) != len(a) {
p = make([]PathEnd, len(a))
for i := range p {
p[i].From = -1
}
f.Paths = p
}
simple = true
p[root].Len = 1
type arc struct {
from NI
half Half
}
var next []arc
frontier := []arc{{-1, Half{root, -1}}}
for len(frontier) > 0 {
for _, fa := range frontier { // fa frontier arc
nSpanned++
l := p[fa.half.To].Len + 1
for _, to := range a[fa.half.To] {
if to.To == fa.from && to.Label == fa.half.Label {
continue
}
if p[to.To].Len > 0 {
simple = false
continue
}
p[to.To] = PathEnd{From: fa.half.To, Len: l}
if len(labels) == len(p) {
labels[to.To] = to.Label
}
if l > f.MaxLen {
f.MaxLen = l
}
next = append(next, arc{fa.half.To, to})
}
}
frontier, next = next, frontier[:0]
}
return
}
// HasEdge returns true if g has any edge between nodes n1 and n2.
//
// Also returned are indexes x1 and x2 such that g[n1][x1] == Half{n2, l}
// and g[n2][x2] == {n1, l} for some label l. If no edge between n1 and n2
// exists, HasArc returns `has` == false.
//
// See also HasArc. If you are only interested in the boolean result then
// HasArc is an adequate test.
func (g LabeledUndirected) HasEdge(n1, n2 NI) (has bool, x1, x2 int) {
if has, x1 = g.HasArc(n1, n2); !has {
return has, x1, x1
}
has, x2 = g.HasArcLabel(n2, n1, g.LabeledAdjacencyList[n1][x1].Label)
return
}
// HasEdgeLabel returns true if g has any edge between nodes n1 and n2 with
// label l.
//
// Also returned are indexes x1 and x2 such that g[n1][x1] == Half{n2, l}
// and g[n2][x2] == Half{n1, l}. If no edge between n1 and n2 with label l
// is present HasArc returns `has` == false.
func (g LabeledUndirected) HasEdgeLabel(n1, n2 NI, l LI) (has bool, x1, x2 int) {
if has, x1 = g.HasArcLabel(n1, n2, l); !has {
return has, x1, x1
}
has, x2 = g.HasArcLabel(n2, n1, l)
return
}
// RemoveEdge removes a single edge between nodes n1 and n2.
//
// It removes reciprocal arcs in the case of distinct n1 and n2 or removes
// a single arc loop in the case of n1 == n2.
//
// If the specified edge is found and successfully removed, RemoveEdge returns
// true and the label of the edge removed. If no edge exists between n1 and n2,
// RemoveEdge returns false, 0.
func (g LabeledUndirected) RemoveEdge(n1, n2 NI) (ok bool, label LI) {
ok, x1, x2 := g.HasEdge(n1, n2)
if !ok {
return
}
a := g.LabeledAdjacencyList
to := a[n1]
label = to[x1].Label // return value
last := len(to) - 1
to[x1] = to[last]
a[n1] = to[:last]
if n1 == n2 {
return
}
to = a[n2]
last = len(to) - 1
to[x2] = to[last]
a[n2] = to[:last]
return
}
// RemoveEdgeLabel removes a single edge between nodes n1 and n2 with label l.
//
// It removes reciprocal arcs in the case of distinct n1 and n2 or removes
// a single arc loop in the case of n1 == n2.
//
// Returns true if the specified edge is found and successfully removed,
// false if the edge does not exist.
func (g LabeledUndirected) RemoveEdgeLabel(n1, n2 NI, l LI) (ok bool) {
ok, x1, x2 := g.HasEdgeLabel(n1, n2, l)
if !ok {
return
}
a := g.LabeledAdjacencyList
to := a[n1]
last := len(to) - 1
to[x1] = to[last]
a[n1] = to[:last]
if n1 == n2 {
return
}
to = a[n2]
last = len(to) - 1
to[x2] = to[last]
a[n2] = to[:last]
return
}
// TarjanBiconnectedComponents decomposes a graph into maximal biconnected
// components, components for which if any node were removed the component
// would remain connected.
//
// The receiver g must be a simple graph. The method calls the emit argument
// for each component identified, as long as emit returns true. If emit
// returns false, TarjanBiconnectedComponents returns immediately.
//
// See also the eqivalent unlabeled TarjanBiconnectedComponents.
func (g LabeledUndirected) TarjanBiconnectedComponents(emit func([]LabeledEdge) bool) {
// Code nearly identical to unlabled version.
number := make([]int, g.Order())
lowpt := make([]int, g.Order())
var stack []LabeledEdge
var i int
var biconnect func(NI, NI) bool
biconnect = func(v, u NI) bool {
i++
number[v] = i
lowpt[v] = i
for _, w := range g.LabeledAdjacencyList[v] {
if number[w.To] == 0 {
stack = append(stack, LabeledEdge{Edge{v, w.To}, w.Label})
if !biconnect(w.To, v) {
return false
}
if lowpt[w.To] < lowpt[v] {
lowpt[v] = lowpt[w.To]
}
if lowpt[w.To] >= number[v] {
var bcc []LabeledEdge
top := len(stack) - 1
for number[stack[top].N1] >= number[w.To] {
bcc = append(bcc, stack[top])
stack = stack[:top]
top--
}
bcc = append(bcc, stack[top])
stack = stack[:top]
top--
if !emit(bcc) {
return false
}
}
} else if number[w.To] < number[v] && w.To != u {
stack = append(stack, LabeledEdge{Edge{v, w.To}, w.Label})
if number[w.To] < lowpt[v] {
lowpt[v] = number[w.To]
}
}
}
return true
}
for w := range g.LabeledAdjacencyList {
if number[w] == 0 && !biconnect(NI(w), -1) {
return
}
}
}
func (e *eulerian) pushUndir() error {
for u := e.top(); ; {
e.uv.SetBit(int(u), 0)
arcs := e.g[u]
if len(arcs) == 0 {
return nil
}
w := arcs[0]
e.s++
e.p[e.s] = w
e.g[u] = arcs[1:] // consume arc
// difference from directed counterpart in dir.go:
// as long as it's not a loop, consume reciprocal arc as well
if w != u {
a2 := e.g[w]
for x, rx := range a2 {
if rx == u { // here it is
last := len(a2) - 1
a2[x] = a2[last] // someone else gets the seat
e.g[w] = a2[:last] // and it's gone.
goto l
}
}
return fmt.Errorf("graph not undirected. %d -> %d reciprocal not found", u, w)
}
l:
u = w
}
}
func (e *labEulerian) pushUndir() error {
for u := e.top(); ; {
e.uv.SetBit(int(u.To), 0)
arcs := e.g[u.To]
if len(arcs) == 0 {
return nil
}
w := arcs[0]
e.s++
e.p[e.s] = w
e.g[u.To] = arcs[1:] // consume arc
// difference from directed counterpart in dir.go:
// as long as it's not a loop, consume reciprocal arc as well
if w.To != u.To {
a2 := e.g[w.To]
for x, rx := range a2 {
if rx.To == u.To && rx.Label == w.Label { // here it is
last := len(a2) - 1
a2[x] = a2[last] // someone else can have the seat
e.g[w.To] = a2[:last] // and it's gone.
goto l
}
}
return fmt.Errorf("graph not undirected. %d -> %v reciprocal not found", u.To, w)
}
l:
u = w
}
}