@@ -207,10 +207,10 @@ julia> g = SimpleDiGraph(Edge.(edge_list))
207
207
208
208
julia> strongly_connected_components(g)
209
209
4-element Array{Array{Int64,1},1}:
210
- [8, 9]
211
- [5, 6, 7]
210
+ [8, 9]
211
+ [5, 6, 7]
212
212
[1, 2, 3, 4]
213
- [10, 11]
213
+ [10, 11]
214
214
215
215
```
216
216
"""
@@ -221,18 +221,18 @@ function strongly_connected_components end
221
221
one_t = one (T)
222
222
nvg = nv (g)
223
223
count = one_t
224
-
225
-
224
+
225
+
226
226
index = zeros (T, nvg) # first time in which vertex is discovered
227
227
stack = Vector {T} () # stores vertices which have been discovered and not yet assigned to any component
228
228
onstack = zeros (Bool, nvg) # false if a vertex is waiting in the stack to receive a component assignment
229
229
lowlink = zeros (T, nvg) # lowest index vertex that it can reach through back edge (index array not vertex id number)
230
230
parents = zeros (T, nvg) # parent of every vertex in dfs
231
231
components = Vector {Vector{T}} () # maintains a list of scc (order is not guaranteed in API)
232
232
233
-
233
+
234
234
dfs_stack = Vector {T} ()
235
-
235
+
236
236
@inbounds for s in vertices (g)
237
237
if index[s] == zero_t
238
238
index[s] = count
@@ -243,8 +243,8 @@ function strongly_connected_components end
243
243
count = count + one_t
244
244
245
245
# start dfs from 's'
246
- push! (dfs_stack, s)
247
-
246
+ push! (dfs_stack, s)
247
+
248
248
while ! isempty (dfs_stack)
249
249
v = dfs_stack[end ] # end is the most recently added item
250
250
u = zero_t
@@ -267,11 +267,11 @@ function strongly_connected_components end
267
267
# time to start popping.
268
268
popped = pop! (dfs_stack)
269
269
lowlink[parents[popped]] = min (lowlink[parents[popped]], lowlink[popped])
270
-
270
+
271
271
if index[v] == lowlink[v]
272
272
# found a cycle in a completed dfs tree.
273
273
component = Vector {T} ()
274
-
274
+
275
275
while ! isempty (stack) # break when popped == v
276
276
# drain stack until we see v.
277
277
# everything on the stack until we see v is in the SCC rooted at v.
@@ -284,19 +284,19 @@ function strongly_connected_components end
284
284
break
285
285
end
286
286
end
287
-
287
+
288
288
reverse! (component)
289
289
push! (components, component)
290
290
end
291
-
291
+
292
292
else # LABEL A
293
293
# add unvisited neighbor to dfs
294
294
index[u] = count
295
295
lowlink[u] = count
296
296
onstack[u] = true
297
297
parents[u] = v
298
298
count = count + one_t
299
-
299
+
300
300
push! (stack, u)
301
301
push! (dfs_stack, u)
302
302
# next iteration of while loop will expand the DFS tree from u.
312
312
"""
313
313
strongly_connected_components_kosaraju(g)
314
314
315
- Compute the strongly connected components of a directed graph `g` using Kosaraju's Algorithm.
315
+ Compute the strongly connected components of a directed graph `g` using Kosaraju's Algorithm.
316
316
(https://en.wikipedia.org/wiki/Kosaraju%27s_algorithm).
317
317
318
318
Return an array of arrays, each of which is the entire connected component.
@@ -345,17 +345,17 @@ julia> g=SimpleDiGraph(11)
345
345
346
346
julia> edge_list=[(1,2),(2,3),(3,4),(4,1),(3,5),(5,6),(6,7),(7,5),(5,8),(8,9),(9,8),(10,11),(11,10)]
347
347
13-element Array{Tuple{Int64,Int64},1}:
348
- (1, 2)
349
- (2, 3)
350
- (3, 4)
351
- (4, 1)
352
- (3, 5)
353
- (5, 6)
354
- (6, 7)
355
- (7, 5)
356
- (5, 8)
357
- (8, 9)
358
- (9, 8)
348
+ (1, 2)
349
+ (2, 3)
350
+ (3, 4)
351
+ (4, 1)
352
+ (3, 5)
353
+ (5, 6)
354
+ (6, 7)
355
+ (7, 5)
356
+ (5, 8)
357
+ (8, 9)
358
+ (9, 8)
359
359
(10, 11)
360
360
(11, 10)
361
361
@@ -364,98 +364,98 @@ julia> g = SimpleDiGraph(Edge.(edge_list))
364
364
365
365
julia> strongly_connected_components_kosaraju(g)
366
366
4-element Array{Array{Int64,1},1}:
367
- [11, 10]
367
+ [11, 10]
368
368
[2, 3, 4, 1]
369
- [6, 7, 5]
370
- [9, 8]
369
+ [6, 7, 5]
370
+ [9, 8]
371
371
372
372
```
373
373
"""
374
374
function strongly_connected_components_kosaraju end
375
375
@traitfn function strongly_connected_components_kosaraju (g:: AG :: IsDirected ) where {T<: Integer , AG <: AbstractGraph{T} }
376
-
377
- nvg = nv (g)
376
+
377
+ nvg = nv (g)
378
378
379
379
components = Vector {Vector{T}} () # Maintains a list of strongly connected components
380
-
380
+
381
381
order = Vector {T} () # Vector which will store the order in which vertices are visited
382
- sizehint! (order, nvg)
383
-
382
+ sizehint! (order, nvg)
383
+
384
384
color = zeros (UInt8, nvg) # Vector used as for marking the colors during dfs
385
-
385
+
386
386
dfs_stack = Vector {T} () # Stack used for dfs
387
-
387
+
388
388
# dfs1
389
389
@inbounds for v in vertices (g)
390
-
391
- color[v] != 0 && continue
390
+
391
+ color[v] != 0 && continue
392
392
color[v] = 1
393
-
393
+
394
394
# Start dfs from v
395
395
push! (dfs_stack, v) # Push v to the stack
396
-
396
+
397
397
while ! isempty (dfs_stack)
398
398
u = dfs_stack[end ]
399
399
w = zero (T)
400
-
400
+
401
401
for u_neighbor in outneighbors (g, u)
402
402
if color[u_neighbor] == 0
403
403
w = u_neighbor
404
404
break
405
405
end
406
406
end
407
-
407
+
408
408
if w != 0
409
409
push! (dfs_stack, w)
410
410
color[w] = 1
411
411
else
412
412
push! (order, u) # Push back in vector to store the order in which the traversal finishes(Reverse Topological Sort)
413
413
color[u] = 2
414
- pop! (dfs_stack)
414
+ pop! (dfs_stack)
415
415
end
416
416
end
417
417
end
418
-
418
+
419
419
@inbounds for i in vertices (g)
420
420
color[i] = 0 # Marking all the vertices from 1 to n as unvisited for dfs2
421
421
end
422
-
422
+
423
423
# dfs2
424
424
@inbounds for i in 1 : nvg
425
-
425
+
426
426
v = order[end - i+ 1 ] # Reading the order vector in the decreasing order of finish time
427
- color[v] != 0 && continue
427
+ color[v] != 0 && continue
428
428
color[v] = 1
429
-
429
+
430
430
component= Vector {T} () # Vector used to store the vertices of one component temporarily
431
-
431
+
432
432
# Start dfs from v
433
433
push! (dfs_stack, v) # Push v to the stack
434
-
434
+
435
435
while ! isempty (dfs_stack)
436
436
u = dfs_stack[end ]
437
437
w = zero (T)
438
-
438
+
439
439
for u_neighbor in inneighbors (g, u)
440
440
if color[u_neighbor] == 0
441
441
w = u_neighbor
442
442
break
443
443
end
444
444
end
445
-
445
+
446
446
if w != 0
447
447
push! (dfs_stack, w)
448
448
color[w] = 1
449
449
else
450
450
color[u] = 2
451
451
push! (component, u) # Push u to the vector component
452
- pop! (dfs_stack)
452
+ pop! (dfs_stack)
453
453
end
454
454
end
455
-
455
+
456
456
push! (components, component)
457
457
end
458
-
458
+
459
459
return components
460
460
end
461
461
@@ -500,11 +500,11 @@ function period end
500
500
501
501
g_bfs_tree = bfs_tree (g, 1 )
502
502
levels = gdistances (g_bfs_tree, 1 )
503
- tree_diff = difference (g, g_bfs_tree)
504
503
edge_values = Vector {T} ()
505
504
506
505
divisor = 0
507
- for e in edges (tree_diff)
506
+ for e in edges (g)
507
+ has_edge (g_bfs_tree, src (e), dst (e)) && continue
508
508
@inbounds value = levels[src (e)] - levels[dst (e)] + 1
509
509
divisor = gcd (divisor, value)
510
510
isequal (divisor, 1 ) && return 1
0 commit comments