-
Notifications
You must be signed in to change notification settings - Fork 2.3k
/
2421-number-of-good-paths.rs
97 lines (80 loc) · 2.56 KB
/
2421-number-of-good-paths.rs
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
use std::{cmp::Ordering, collections::HashMap};
struct UnionFind {
parent: Vec<usize>,
rank: Vec<i32>,
}
impl UnionFind {
fn new(n: usize) -> Self {
UnionFind {
parent: (0..n).collect(),
rank: vec![0; n],
}
}
fn find(&mut self, mut i: usize) -> usize {
while i != self.parent[i] {
self.parent[i] = self.parent[self.parent[i]];
i = self.parent[i];
}
i
}
fn union(&mut self, a: usize, b: usize) -> bool {
let a_root = self.find(a);
let b_root = self.find(b);
if a_root == b_root {
return false;
}
match self.rank[a_root].cmp(&self.rank[b_root]) {
Ordering::Less => {
self.parent[a_root] = b_root;
self.rank[b_root] += self.rank[a_root];
}
_ => {
self.parent[b_root] = a_root;
self.rank[a_root] = self.rank[b_root];
}
}
true
}
}
impl Solution {
pub fn number_of_good_paths(vals: Vec<i32>, edges: Vec<Vec<i32>>) -> i32 {
let adj = Self::create_adj_list(&edges);
let val_to_index = Self::create_val_to_index(&vals);
let mut res = 0;
let mut uf = UnionFind::new(vals.len());
let mut keys: Vec<i32> = val_to_index.keys().cloned().collect();
keys.sort();
for val in keys {
for i in val_to_index.get(&val).unwrap_or(&vec![]) {
for nei in adj.get(&(*i as i32)).unwrap_or(&vec![]) {
if vals[*nei as usize] <= vals[*i] {
uf.union(*nei as usize, *i);
}
}
}
let mut count = HashMap::new();
for i in val_to_index.get(&val).unwrap() {
*count.entry(uf.find(*i)).or_insert(0) += 1;
res += count.get(&uf.find(*i)).unwrap();
}
}
res
}
pub fn create_adj_list(edges: &Vec<Vec<i32>>) -> HashMap<i32, Vec<i32>> {
let mut adj = HashMap::new();
for edge in edges {
let a = edge[0];
let b = edge[1];
adj.entry(a).or_insert(vec![]).push(b);
adj.entry(b).or_insert(vec![]).push(a);
}
adj
}
pub fn create_val_to_index(vals: &Vec<i32>) -> HashMap<i32, Vec<usize>> {
let mut val_to_index = HashMap::new();
for (i, val) in vals.iter().enumerate() {
val_to_index.entry(*val).or_insert(vec![]).push(i);
}
val_to_index
}
}