haar_lib/graph/
functional_graph.rs1use crate::ds::unionfind::UnionFind;
7
8pub struct FunctionalGraphBuilder {
10 next: Vec<Option<usize>>,
11}
12
13#[derive(Clone, Copy, PartialEq, Debug)]
15pub enum Kind {
16 Loop,
18 Branch,
20 Leaf,
22}
23
24impl Kind {
25 pub fn is_loop(self) -> bool {
27 matches!(self, Self::Loop)
28 }
29
30 pub fn is_branch(self) -> bool {
32 matches!(self, Self::Branch)
33 }
34
35 pub fn is_leaf(self) -> bool {
37 matches!(self, Self::Leaf)
38 }
39}
40
41#[derive(Clone, Default, Debug)]
43pub struct Group {
44 pub loops: Vec<usize>,
46 pub branches: Vec<usize>,
48 pub leaves: Vec<usize>,
50}
51
52pub struct FunctionalGraph {
54 next: Vec<usize>,
55 v_kind: Vec<Kind>,
56 group_index: Vec<usize>,
57 groups: Vec<Group>,
58 children: Vec<Vec<usize>>,
59}
60
61impl FunctionalGraphBuilder {
62 pub fn new(n: usize) -> Self {
64 Self {
65 next: vec![None; n],
66 }
67 }
68
69 pub fn add(&mut self, from: usize, to: usize) {
71 assert!(self.next[from].is_none());
72 self.next[from] = Some(to);
73 }
74
75 pub fn build(self) -> FunctionalGraph {
77 assert!(self.next.iter().all(|a| a.is_some()));
78
79 let next = self.next.into_iter().flatten().collect::<Vec<_>>();
80 let n = next.len();
81
82 let mut uf = UnionFind::new(n);
83 for (cur, &next) in next.iter().enumerate() {
84 uf.merge(cur, next);
85 }
86
87 let mut index = vec![0; n];
88 let g_num = index
89 .iter_mut()
90 .enumerate()
91 .filter_map(|(i, index)| (uf.root_of(i) == i).then_some(index))
92 .enumerate()
93 .map(|(i, index)| *index = i)
94 .count();
95
96 let mut groups = vec![Group::default(); g_num];
97 let mut group_index = vec![0; n];
98
99 let mut in_deg = vec![0; n];
100 for &next in &next {
101 in_deg[next] += 1;
102 }
103
104 let mut v_kind = vec![None; n];
105 let mut stack = in_deg
106 .iter()
107 .enumerate()
108 .filter_map(|(i, &d)| (d == 0).then_some(i))
109 .inspect(|&i| {
110 v_kind[i] = Some(Kind::Leaf);
111 group_index[i] = index[uf.root_of(i)];
112 groups[group_index[i]].leaves.push(i);
113 })
114 .collect::<Vec<_>>();
115
116 while let Some(cur) = stack.pop() {
117 if v_kind[cur].is_none() {
118 v_kind[cur] = Some(Kind::Branch);
119 group_index[cur] = index[uf.root_of(cur)];
120 groups[group_index[cur]].branches.push(cur);
121 }
122
123 let next = next[cur];
124 in_deg[next] -= 1;
125 if in_deg[next] == 0 {
126 stack.push(next);
127 }
128 }
129
130 for i in 0..n {
131 if in_deg[i] != 0 {
132 v_kind[i] = Some(Kind::Loop);
133 group_index[i] = index[uf.root_of(i)];
134 groups[group_index[i]].loops.push(i);
135 }
136 }
137
138 let mut children = vec![vec![]; n];
139 for (i, &p) in next.iter().enumerate() {
140 if !v_kind[i].unwrap().is_loop() {
141 children[p].push(i);
142 }
143 }
144
145 FunctionalGraph {
146 next,
147 v_kind: v_kind.into_iter().flatten().collect(),
148 group_index,
149 groups,
150 children,
151 }
152 }
153}
154
155impl FunctionalGraph {
156 pub fn next_of(&self, i: usize) -> usize {
158 self.next[i]
159 }
160
161 pub fn kind_of(&self, i: usize) -> Kind {
163 self.v_kind[i]
164 }
165
166 pub fn group_index_of(&self, i: usize) -> usize {
168 self.group_index[i]
169 }
170
171 pub fn group_of(&self, i: usize) -> &Group {
173 &self.groups[self.group_index_of(i)]
174 }
175
176 pub fn groups(&self) -> &[Group] {
178 &self.groups
179 }
180
181 pub fn children(&self, i: usize) -> impl Iterator<Item = usize> + '_ {
183 self.children[i].iter().copied()
184 }
185}