...
1
2
3
4
5 package plotter
6
7
8
9
10
11
12 type johnson struct {
13 adjacent graph
14 b []set
15 blocked []bool
16 s int
17
18 stack []int
19
20 result [][]int
21 }
22
23
24 func cyclesIn(g graph) [][]int {
25 j := johnson{
26 adjacent: g.clone(),
27 b: make([]set, len(g)),
28 blocked: make([]bool, len(g)),
29 }
30
31
32
33
34 for j.s < len(j.adjacent)-1 {
35
36 t := newTarjan(j.adjacent.subgraph(j.s))
37
38
39 j.adjacent = t.sccSubGraph(2)
40 if len(j.adjacent) == 0 {
41 break
42 }
43
44
45 for _, v := range j.adjacent {
46 s := len(j.adjacent)
47 for n := range v {
48 if n < s {
49 s = n
50 }
51 }
52 if s < j.s {
53 j.s = s
54 }
55 }
56 for i, v := range j.adjacent {
57 if len(v) > 0 {
58 j.blocked[i] = false
59 j.b[i] = make(set)
60 }
61 }
62
63
64 _ = j.circuit(j.s)
65 j.s++
66 }
67
68 return j.result
69 }
70
71
72 func (j *johnson) circuit(v int) bool {
73 f := false
74 j.stack = append(j.stack, v)
75 j.blocked[v] = true
76
77
78 for w := range j.adjacent[v] {
79 if w == j.s {
80
81 r := make([]int, len(j.stack)+1)
82 copy(r, j.stack)
83 r[len(r)-1] = j.s
84 j.result = append(j.result, r)
85 f = true
86 } else if !j.blocked[w] {
87 if j.circuit(w) {
88 f = true
89 }
90 }
91 }
92
93
94 if f {
95 j.unblock(v)
96 } else {
97 for w := range j.adjacent[v] {
98 j.b[w][v] = struct{}{}
99 }
100 }
101 j.stack = j.stack[:len(j.stack)-1]
102
103 return f
104 }
105
106
107 func (j *johnson) unblock(u int) {
108 j.blocked[u] = false
109 for w := range j.b[u] {
110 delete(j.b[u], w)
111 if j.blocked[w] {
112 j.unblock(w)
113 }
114 }
115 }
116
117 func min(a, b int) int {
118 if a < b {
119 return a
120 }
121 return b
122 }
123
124
125
126
127
128 type tarjan struct {
129 g graph
130
131 index int
132 indexTable []int
133 lowLink []int
134 onStack []bool
135
136 stack []int
137
138 sccs [][]int
139 }
140
141
142
143 func newTarjan(g graph) *tarjan {
144 t := tarjan{
145 g: g,
146
147 indexTable: make([]int, len(g)),
148 lowLink: make([]int, len(g)),
149 onStack: make([]bool, len(g)),
150 }
151 for v := range t.g {
152 if t.indexTable[v] == 0 {
153 t.strongconnect(v)
154 }
155 }
156 return &t
157 }
158
159
160
161 func (t *tarjan) strongconnect(v int) {
162
163 t.index++
164 t.indexTable[v] = t.index
165 t.lowLink[v] = t.index
166 t.stack = append(t.stack, v)
167 t.onStack[v] = true
168
169
170 for w := range t.g[v] {
171 if t.indexTable[w] == 0 {
172
173 t.strongconnect(w)
174 t.lowLink[v] = min(t.lowLink[v], t.lowLink[w])
175 } else if t.onStack[w] {
176
177 t.lowLink[v] = min(t.lowLink[v], t.indexTable[w])
178 }
179 }
180
181
182 if t.lowLink[v] == t.indexTable[v] {
183
184 var (
185 scc []int
186 w int
187 )
188 for {
189 w, t.stack = t.stack[len(t.stack)-1], t.stack[:len(t.stack)-1]
190 t.onStack[w] = false
191
192 scc = append(scc, w)
193 if w == v {
194 break
195 }
196 }
197
198 t.sccs = append(t.sccs, scc)
199 }
200 }
201
202
203
204
205
206 func (t *tarjan) sccSubGraph(min int) graph {
207 if len(t.g) == 0 {
208 return nil
209 }
210 sub := make(graph, len(t.g))
211
212 var n int
213 for _, scc := range t.sccs {
214 if len(scc) < min {
215 continue
216 }
217 n++
218 for _, u := range scc {
219 for _, v := range scc {
220 if _, ok := t.g[u][v]; ok {
221 if sub[u] == nil {
222 sub[u] = make(set)
223 }
224 sub[u][v] = struct{}{}
225 }
226 }
227 }
228 }
229 if n == 0 {
230 return nil
231 }
232
233 return sub
234 }
235
236
237 type set map[int]struct{}
238
239
240 type graph []set
241
242
243 func (g graph) remove(paths [][]int) {
244 for _, p := range paths {
245 for i, u := range p[:len(p)-1] {
246 delete(g[u], p[i+1])
247 }
248 }
249 }
250
251
252
253 func (g graph) subgraph(s int) graph {
254 for u := range g[:s] {
255 g[u] = nil
256 }
257 for u, e := range g[s:] {
258 for v := range e {
259 if v < s {
260 delete(g[u+s], v)
261 }
262 }
263 }
264 return g
265 }
266
267
268 func (g graph) clone() graph {
269 c := make(graph, len(g))
270 for u, e := range g {
271 for v := range e {
272 if c[u] == nil {
273 c[u] = make(set)
274 }
275 c[u][v] = struct{}{}
276 }
277 }
278 return c
279 }
280
View as plain text