1use params::{Owned, ParamDerefMut};
9use prelude::*;
10
11use fera_fun::first;
12use fera_unionfind::UnionFind as InnerUnionFind;
13
14pub struct UnionFind<G: Graph> {
17 inner: InnerUnionFind<
18 Vertex<G>,
19 DefaultVertexPropMut<G, Vertex<G>>,
20 DefaultVertexPropMut<G, usize>,
21 >,
22}
23
24impl<G: Graph> UnionFind<G> {
25 #[inline]
26 pub fn union(&mut self, u: Vertex<G>, v: Vertex<G>) {
27 self.inner.union(u, v)
28 }
29
30 #[inline]
31 pub fn in_same_set(&mut self, u: Vertex<G>, v: Vertex<G>) -> bool {
32 self.inner.in_same_set(u, v)
33 }
34
35 #[inline]
36 pub fn find_set(&mut self, v: Vertex<G>) -> Vertex<G> {
37 self.inner.find_set(v)
38 }
39
40 #[inline]
41 pub fn num_sets(&self) -> usize {
42 self.inner.num_sets()
43 }
44
45 pub fn reset(&mut self, g: &G) {
46 for v in g.vertices() {
47 self.inner.make_set(v)
48 }
49 }
50}
51
52pub trait WithUnionFind: Graph {
53 fn new_unionfind(&self) -> UnionFind<Self> {
54 let v = first(self.vertices());
56 let mut parent = self.default_vertex_prop(v);
57 for v in self.vertices() {
58 parent[v] = v;
59 }
60 UnionFind {
61 inner: InnerUnionFind::with_parent_rank_num_sets(
62 parent,
63 self.vertex_prop(0),
64 self.num_vertices(),
65 ),
66 }
67 }
68}
69
70impl<G: Graph> WithUnionFind for G {}
71
72pub struct NewUnionFind<'a, G: 'a>(pub &'a G);
73
74impl<'a, G: 'a + WithUnionFind> ParamDerefMut for NewUnionFind<'a, G> {
75 type Target = UnionFind<G>;
76 type Output = Owned<UnionFind<G>>;
77
78 fn build(self) -> Self::Output {
79 Owned(self.0.new_unionfind())
80 }
81}
82
83#[cfg(test)]
84mod tests {
85 use super::{UnionFind, WithUnionFind};
86 use fera_fun::vec;
87 use prelude::*;
88
89 fn check_groups(
90 ds: &mut UnionFind<StaticGraph>,
91 num_sets: usize,
92 groups: &[&[Vertex<StaticGraph>]],
93 ) {
94 assert_eq!(num_sets, ds.num_sets());
95 for group in groups {
96 for &a in *group {
97 assert!(ds.in_same_set(group[0], a));
98 }
99 }
100 }
101
102 #[test]
103 fn unionfind() {
104 let g: StaticGraph = graph!(5);
105 let v = vec(g.vertices());
106 let mut ds = g.new_unionfind();
107 assert_eq!(5, ds.num_sets());
108 ds.union(v[0], v[2]);
109 check_groups(&mut ds, 4, &[&[v[0], v[2]]]);
110 ds.union(v[1], v[3]);
111 check_groups(&mut ds, 3, &[&[v[0], v[2]], &[v[1], v[3]]]);
112 ds.union(v[2], v[4]);
113 check_groups(&mut ds, 2, &[&[v[0], v[2], v[4]], &[v[1], v[3]]]);
114 ds.union(v[3], v[4]);
115 check_groups(&mut ds, 1, &[&[v[0], v[2], v[4], v[1], v[3]]]);
116 }
117}