@@ -291,7 +291,9 @@ function acyclic_coloring(
291291 end
292292 end
293293
294- tree_set = TreeSet (g, forest)
294+ buffer = forbidden_colors
295+ reverse_bfs_orders = first_visit_to_tree
296+ tree_set = TreeSet (g, forest, buffer, reverse_bfs_orders)
295297 if postprocessing
296298 # Reuse the vector forbidden_colors to compute offsets during post-processing
297299 offsets = forbidden_colors
@@ -372,19 +374,29 @@ Encode a set of 2-colored trees resulting from the [`acyclic_coloring`](@ref) al
372374$TYPEDFIELDS
373375"""
374376struct TreeSet{T}
375- reverse_bfs_orders:: Vector{Vector{ Tuple{T,T} }}
377+ reverse_bfs_orders:: Vector{Tuple{T,T}}
376378 is_star:: Vector{Bool}
379+ num_edges_per_tree:: Vector{T}
377380end
378381
379- function TreeSet (g:: AdjacencyGraph{T} , forest:: Forest{T} ) where {T}
382+ function TreeSet (
383+ g:: AdjacencyGraph{T} ,
384+ forest:: Forest{T} ,
385+ buffer:: AbstractVector{T} ,
386+ reverse_bfs_orders:: Vector{Tuple{T,T}} ,
387+ ) where {T}
380388 S = pattern (g)
381389 edge_to_index = edge_indices (g)
382390 nv = nb_vertices (g)
383391 nt = forest. num_trees
384392
385- # dictionary that maps a tree's root to the index of the tree
386- roots = Dict {T,T} ()
387- sizehint! (roots, nt)
393+ # root_to_tree is a vector that maps a tree's root to the index of the tree
394+ # We can recycle forest.ranks because we don't need it anymore to merge trees
395+ root_to_tree = forest. ranks
396+ fill! (root_to_tree, zero (T))
397+
398+ # Contains the number of edges per tree
399+ num_edges_per_tree = zeros (T, nt)
388400
389401 # vector of dictionaries where each dictionary stores the neighbors of each vertex in a tree
390402 trees = [Dict {T,Vector{T}} () for i in 1 : nt]
@@ -401,13 +413,14 @@ function TreeSet(g::AdjacencyGraph{T}, forest::Forest{T}) where {T}
401413 root = find_root! (forest, index_ij)
402414
403415 # Update roots
404- if ! haskey (roots, root)
416+ if iszero (root_to_tree[ root] )
405417 nr += 1
406- roots [root] = nr
418+ root_to_tree [root] = nr
407419 end
408420
409421 # index of the tree T that contains this edge
410- index_tree = roots[root]
422+ index_tree = root_to_tree[root]
423+ num_edges_per_tree[index_tree] += 1
411424
412425 # Update the neighbors of i in the tree T
413426 if ! haskey (trees[index_tree], i)
@@ -427,10 +440,7 @@ function TreeSet(g::AdjacencyGraph{T}, forest::Forest{T}) where {T}
427440 end
428441
429442 # degrees is a vector of integers that stores the degree of each vertex in a tree
430- degrees = Vector {T} (undef, nv)
431-
432- # reverse breadth first (BFS) traversal order for each tree in the forest
433- reverse_bfs_orders = [Tuple{T,T}[] for i in 1 : nt]
443+ degrees = buffer
434444
435445 # nvmax is the number of vertices of the biggest tree in the forest
436446 nvmax = 0
@@ -446,6 +456,10 @@ function TreeSet(g::AdjacencyGraph{T}, forest::Forest{T}) where {T}
446456 # meaning that one vertex is directly connected to all other vertices in the tree
447457 is_star = Vector {Bool} (undef, nt)
448458
459+ # Number of edges treated
460+ num_edges_treated = zero (T)
461+
462+ # reverse_bfs_orders contains the reverse breadth first (BFS) traversal order for each tree in the forest
449463 for k in 1 : nt
450464 tree = trees[k]
451465
@@ -483,7 +497,8 @@ function TreeSet(g::AdjacencyGraph{T}, forest::Forest{T}) where {T}
483497 # Check if neighbor is the parent of the leaf or if it was a child before the tree was pruned
484498 if degrees[neighbor] != 0
485499 # (leaf, neighbor) represents the next edge to visit during decompression
486- push! (reverse_bfs_orders[k], (leaf, neighbor))
500+ num_edges_treated += 1
501+ reverse_bfs_orders[num_edges_treated] = (leaf, neighbor)
487502
488503 if bool_star
489504 # Initialize the potential hub of the star with the first parent of a leaf
@@ -514,7 +529,7 @@ function TreeSet(g::AdjacencyGraph{T}, forest::Forest{T}) where {T}
514529 is_star[k] = bool_star
515530 end
516531
517- return TreeSet (reverse_bfs_orders, is_star)
532+ return TreeSet (reverse_bfs_orders, is_star, num_edges_per_tree )
518533end
519534
520535# # Postprocessing, mirrors decompression code
@@ -582,46 +597,52 @@ function postprocess!(
582597 end
583598 else
584599 # only the colors of non-leaf vertices are used
585- (; reverse_bfs_orders, is_star) = star_or_tree_set
600+ (; reverse_bfs_orders, is_star, num_edges_per_tree ) = star_or_tree_set
586601 nb_trivial_trees = 0
587602
603+ # Index of the first edge in reverse_bfs_orders for the current tree
604+ first = 1
605+
588606 # Iterate through all non-trivial trees
589- for k in eachindex (reverse_bfs_orders )
590- reverse_bfs_order = reverse_bfs_orders [k]
607+ for k in eachindex (num_edges_per_tree )
608+ ne_tree = num_edges_per_tree [k]
591609 # Check if we have more than one edge in the tree (non-trivial tree)
592- if length (reverse_bfs_order) > 1
610+ if ne_tree > 1
593611 # Determine if the tree is a star
594612 if is_star[k]
595613 # It is a non-trivial star and only the color of the hub is needed
596- (_, hub) = reverse_bfs_order[ 1 ]
614+ (_, hub) = reverse_bfs_orders[first ]
597615 color_used[color[hub]] = true
598616 else
599617 # It is not a star and both colors are needed during the decompression
600- (i, j) = reverse_bfs_order[ 1 ]
618+ (i, j) = reverse_bfs_orders[first ]
601619 color_used[color[i]] = true
602620 color_used[color[j]] = true
603621 end
604622 else
605623 nb_trivial_trees += 1
606624 end
625+ first += ne_tree
607626 end
608627
609628 # Process the trivial trees (if any)
610629 if nb_trivial_trees > 0
611- for k in eachindex (reverse_bfs_orders)
612- reverse_bfs_order = reverse_bfs_orders[k]
630+ first = 1
631+ for k in eachindex (num_edges_per_tree)
632+ ne_tree = num_edges_per_tree[k]
613633 # Check if we have exactly one edge in the tree
614- if length (reverse_bfs_order) == 1
615- (i, j) = reverse_bfs_order[ 1 ]
634+ if ne_tree == 1
635+ (i, j) = reverse_bfs_orders[first ]
616636 if color_used[color[i]]
617637 # Make i the root to avoid possibly adding one more used color
618638 # Switch it with the (only) leaf
619- reverse_bfs_order[ 1 ] = (j, i)
639+ reverse_bfs_orders[first ] = (j, i)
620640 else
621641 # Keep j as the root
622642 color_used[color[j]] = true
623643 end
624644 end
645+ first += ne_tree
625646 end
626647 end
627648 end
0 commit comments