Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit f7e1f71

Browse files
committed
DFS API now returns edges, skips root
1 parent 1c6f43a commit f7e1f71

File tree

4 files changed

+46
-40
lines changed

4 files changed

+46
-40
lines changed

‎README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ Rather than try to persuade you with words, this repository aims to show by exam
6969
### [Network flows](src/graph/flow.rs)
7070

7171
- Dinic's blocking maximum flow
72+
- Minimum cut
7273
- Hopcroft-Karp bipartite matching
7374
- Minimum cost maximum flow
7475

‎src/graph/mod.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -130,14 +130,18 @@ mod test {
130130

131131
#[test]
132132
fn test_adj_list() {
133-
let mut graph = Graph::new(4, 4);
134-
graph.add_edge(0, 1);
133+
let mut graph = Graph::new(5, 6);
134+
graph.add_edge(2, 3);
135+
graph.add_edge(2, 4);
136+
graph.add_edge(4, 1);
135137
graph.add_edge(1, 2);
136-
graph.add_edge(1, 3);
137-
graph.add_edge(3, 0);
138+
graph.add_undirected_edge(0, 2);
138139

139-
let adj:Vec<(usize,usize)>= graph.adj_list(1).collect();
140+
let adj= graph.adj_list(2).collect::<Vec<_>>();
140141

141-
assert_eq!(adj, vec![(2, 3), (1, 2)]);
142+
assert_eq!(adj, vec![(5, 0), (1, 4), (0, 3)]);
143+
for (e, v) in adj {
144+
assert_eq!(v, graph.endp[e]);
145+
}
142146
}
143147
}

‎src/graph/util.rs

Lines changed: 34 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,16 @@ impl Graph {
6161
dist
6262
}
6363

64-
pub fn dfs(&self, u: usize) -> DfsIterator {
64+
pub fn dfs(&self, root: usize) -> DfsIterator {
65+
let mut visited = vec![false; self.num_v()];
66+
visited[root] = true;
6567
let adj_iters = (0..self.num_v())
6668
.map(|u| self.adj_list(u))
6769
.collect::<Vec<_>>();
6870

6971
DfsIterator {
70-
visited:vec![false;self.num_v()],
71-
stack: vec![u],
72+
visited,
73+
stack: vec![root],
7274
adj_iters,
7375
}
7476
}
@@ -81,32 +83,23 @@ pub struct DfsIterator<'a> {
8183
}
8284

8385
impl<'a> Iterator for DfsIterator<'a> {
84-
type Item = usize;
86+
type Item = (usize,usize);
8587

86-
/// Returns next vertex in the DFS
88+
/// Returns next edge and vertex in the depth-first traversal
89+
// Refs: https://www.geeksforgeeks.org/iterative-depth-first-traversal/
90+
// https://en.wikipedia.org/wiki/Depth-first_search
8791
fn next(&mut self) -> Option<Self::Item> {
88-
// Sources:
89-
// https://www.geeksforgeeks.org/iterative-depth-first-traversal/
90-
// https://en.wikipedia.org/wiki/Depth-first_search
91-
while let Some(&u) = self.stack.last() {
92-
if let Some((_, v)) = self.adj_iters[u].next() {
92+
loop {
93+
let &u = self.stack.last()?;
94+
while let Some((e, v)) = self.adj_iters[u].next() {
9395
if !self.visited[v] {
96+
self.visited[v] = true;
9497
self.stack.push(v);
98+
return Some((e, v));
9599
}
96-
} else {
97-
self.stack.pop();
98-
}
99-
100-
// Stack may contain same vertex twice. So
101-
// we return the popped item only
102-
// if it is not visited.
103-
if !self.visited[u] {
104-
self.visited[u] = true;
105-
return Some(u);
106100
}
101+
self.stack.pop();
107102
}
108-
109-
None
110103
}
111104
}
112105

@@ -153,31 +146,38 @@ mod test {
153146

154147
#[test]
155148
fn test_dfs() {
156-
let mut graph = Graph::new(4, 8);
149+
let mut graph = Graph::new(4, 6);
157150
graph.add_edge(0, 2);
158151
graph.add_edge(2, 0);
159152
graph.add_edge(1, 2);
160153
graph.add_edge(0, 1);
161154
graph.add_edge(3, 3);
162155
graph.add_edge(2, 3);
163156

164-
let dfs_search = graph.dfs(2).collect::<Vec<_>>();
165-
assert_eq!(dfs_search, vec![2, 3, 0, 1]);
157+
let dfs_root = 2;
158+
let dfs_traversal = std::iter::once(dfs_root)
159+
.chain(graph.dfs(dfs_root).map(|(_, v)| v))
160+
.collect::<Vec<_>>();
161+
162+
assert_eq!(dfs_traversal, vec![2, 3, 0, 1]);
166163
}
167164

168165
#[test]
169166
fn test_dfs2() {
170-
let mut graph = Graph::new(5, 8);
167+
let mut graph = Graph::new(5, 6);
171168
graph.add_edge(0, 2);
172169
graph.add_edge(2, 1);
173170
graph.add_edge(1, 0);
174171
graph.add_edge(0, 3);
175172
graph.add_edge(3, 4);
176173
graph.add_edge(4, 0);
177174

178-
let dfs_search = graph.dfs(0).collect::<Vec<_>>();
179-
//Note this is not the only valid DFS
180-
assert_eq!(dfs_search, vec![0, 3, 4, 2, 1]);
175+
let dfs_root = 0;
176+
let dfs_traversal = std::iter::once(dfs_root)
177+
.chain(graph.dfs(dfs_root).map(|(_, v)| v))
178+
.collect::<Vec<_>>();
179+
180+
assert_eq!(dfs_traversal, vec![0, 3, 4, 2, 1]);
181181
}
182182

183183
#[test]
@@ -190,10 +190,11 @@ mod test {
190190
}
191191
}
192192

193-
let mut dfs_search = graph.dfs(7);
194-
let mut dfs_check = vec![];
195-
for _ in 0..num_v {
196-
dfs_check.push(dfs_search.next().unwrap());
193+
let dfs_root = 7;
194+
let mut dfs_search = graph.dfs(dfs_root);
195+
let mut dfs_check = vec![dfs_root];
196+
for _ in 1..num_v {
197+
dfs_check.push(dfs_search.next().unwrap().1);
197198
assert!(dfs_search.stack.len() <= num_v + 1);
198199
}
199200

‎src/order.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ impl SparseIndex {
8080
/// It combines the offline algorithm with square root decomposition, resulting in an
8181
/// asymptotically suboptimal but simple algorithm with good amortized performance:
8282
/// N inserts interleaved with Q queries yields O(N sqrt Q + Q log N) time complexity
83-
/// in general, or O(N + Q log N) if all queries come after all inserts.
83+
/// in general, or O((N + Q) log N) if all queries come after all inserts.
8484
// Proof: the Q log N term comes from calls to slice_lower_bound(). As for the N sqrt Q,
8585
// note that between successive times when the hull is rebuilt, O(N) work is done,
8686
// and the running totals of insertions and queries satisfy del_N (del_Q + 1) > N.

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /