1use std::cmp::Ordering;
4
5pub fn connected_components<T: AsRef<[impl AsRef<[usize]>]>>(data: T) -> Vec<usize> {
23 let data = data.as_ref();
24 if data.is_empty() {
25 return vec![];
26 }
27
28 let max_id = *data
30 .iter()
31 .flat_map(|ids| ids.as_ref().iter())
32 .max()
33 .unwrap_or(&0);
34
35 let n = max_id + 1;
36 let mut uf = UnionFind::new(n);
37
38 for ids in data {
43 let ids = ids.as_ref();
44 if ids.len() > 1 {
45 let &base = ids.iter().min().unwrap();
46 for &node in ids {
47 if node != base {
48 uf.union(base, node);
49 }
50 }
51 }
52 }
53
54 let mut result = vec![0; n];
57 for (i, res) in result.iter_mut().enumerate() {
58 let root = uf.find(i);
59 *res = uf.min_element[root];
61 }
62
63 result
64}
65
66struct UnionFind {
67 parent: Vec<usize>,
68 rank: Vec<usize>,
69 min_element: Vec<usize>,
70}
71
72impl UnionFind {
73 fn new(n: usize) -> Self {
74 Self {
75 parent: (0..n).collect(),
76 rank: vec![0; n],
77 min_element: (0..n).collect(),
78 }
79 }
80
81 fn find(&mut self, x: usize) -> usize {
82 if self.parent[x] != x {
83 self.parent[x] = self.find(self.parent[x]);
84 }
85 self.parent[x]
86 }
87
88 fn union(&mut self, x: usize, y: usize) {
89 let rx = self.find(x);
90 let ry = self.find(y);
91
92 if rx != ry {
93 let min_element = self.min_element[rx].min(self.min_element[ry]);
95 match self.rank[rx].cmp(&self.rank[ry]) {
96 Ordering::Less => {
97 self.parent[rx] = ry;
98 self.min_element[ry] = min_element;
99 }
100 Ordering::Greater => {
101 self.parent[ry] = rx;
102 self.min_element[rx] = min_element;
103 }
104 Ordering::Equal => {
105 self.parent[ry] = rx;
106 self.min_element[rx] = min_element;
107 self.rank[rx] += 1;
108 }
109 }
110 }
111 }
112}