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
use prelude::*;
use props::{Color, IgnoreWriteProp};
use traverse::*;
use params::*;
use std::iter;
pub trait RecursiveDfs: WithEdge {
fn recursive_dfs<V>(
&self,
vis: V,
) -> RecursiveDfsAlg<&Self, V, AllVertices<Self>, NewVertexProp<Self, Color>>
where
V: Visitor<Self>,
{
RecursiveDfsAlg(
self,
vis,
AllVertices(self),
NewVertexProp(self, Color::White),
)
}
}
impl<G: WithEdge> RecursiveDfs for G {}
generic_struct! {
#[must_use = "call .run() to execute the algorithm"]
pub struct RecursiveDfsAlg(graph, visitor, roots, color)
}
impl<'a, G, V, R, C> RecursiveDfsAlg<&'a G, V, R, C> {
pub fn run(self) -> Control
where
G: Incidence,
V: Visitor<G>,
R: IntoIterator<Item = Vertex<G>>,
C: ParamDerefMut,
C::Target: VertexPropMut<G, Color>,
{
let RecursiveDfsAlg(g, mut vis, roots, color) = self;
return_unless!(vis.start(g));
let mut color = color.build();
for v in roots {
if color[v] == Color::White {
color[v] = Color::Gray;
return_unless!(vis.discover_root_vertex(g, v));
return_unless!(recursive_dfs_visit(
g,
G::edge_none(),
v,
&mut *color,
&mut vis
));
return_unless!(vis.finish_root_vertex(g, v));
}
}
vis.finish(g)
}
pub fn root(self, root: Vertex<G>) -> RecursiveDfsAlg<&'a G, V, iter::Once<Vertex<G>>, C>
where
G: WithVertex,
{
self.roots(iter::once(root))
}
pub fn ignore_color_changes(self) -> RecursiveDfsAlg<&'a G, V, R, Owned<IgnoreWriteProp<Color>>>
where
G: WithVertex,
{
let color = Owned(self.0.vertex_prop(Color::White));
self.color(color)
}
}
pub fn recursive_dfs_visit<G, C, V>(
g: &G,
from: OptionEdge<G>,
u: Vertex<G>,
color: &mut C,
vis: &mut V,
) -> Control
where
G: Incidence,
C: VertexPropMut<G, Color>,
V: Visitor<G>,
{
color[u] = Color::Gray;
return_unless!(vis.discover_vertex(g, u));
for e in g.out_edges(u) {
let v = g.target(e);
if g.orientation(e).is_undirected() && color[v] == Color::Black || G::edge_some(e) == from {
continue;
}
return_unless!(vis.discover_edge(g, e));
match color[v] {
Color::White => {
return_unless!(vis.discover_tree_edge(g, e));
return_unless!(recursive_dfs_visit(g, e.into(), v, color, vis));
return_unless!(vis.finish_tree_edge(g, e));
}
Color::Gray => {
return_unless!(vis.discover_back_edge(g, e));
}
Color::Black => {
return_unless!(vis.discover_cross_or_forward_edge(g, e));
}
}
return_unless!(vis.finish_edge(g, e));
}
color[u] = Color::Black;
return_unless!(vis.finish_vertex(g, u));
Control::Continue
}