-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathminimize-malware-spread.rs
85 lines (69 loc) · 1.81 KB
/
minimize-malware-spread.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
struct DSU {
s: Vec<i32>,
}
impl DSU {
pub fn new(n: usize) -> Self {
DSU { s: vec![-1; n] }
}
pub fn find(&mut self, i: usize) -> usize {
if self.s[i] < 0 {
return i;
}
self.s[i] = self.find(self.s[i] as usize) as i32;
self.s[i] as usize
}
pub fn join(&mut self, mut a: usize, mut b: usize) -> bool {
a = self.find(a);
b = self.find(b);
if a == b {
return false;
}
if self.s[a] == self.s[b] {
self.s[a] -= 1;
}
let (par, kid) = match self.s[a] <= self.s[b] {
true => (a, b),
false => (b, a),
};
self.s[kid] = par as i32;
self.s[par] -= 1;
return true;
}
}
impl Solution {
pub fn min_malware_spread(graph: Vec<Vec<i32>>, initial: Vec<i32>) -> i32 {
let mut sets = DSU::new(graph.len());
graph.iter().enumerate().for_each(|(i, row)| {
row.iter().enumerate().for_each(|(j, cell)| {
if *cell == 1 {
sets.join(i, j);
}
})
});
let initial_component_freq = initial.iter().fold(vec![0; graph.len()], |mut acc, e| {
acc[sets.find(*e as usize)] += 1;
acc
});
let compoment_totals = (0..graph.len()).fold(vec![0; graph.len()], |mut acc, e| {
acc[sets.find(e)] += 1;
acc
});
let saved_parents = (0..graph.len()).map(|i| sets.find(i)).collect::<Vec<usize>>();
let update_best = |(idx, val): (i32, i32), e: &i32| -> (i32, i32) {
let tot = compoment_totals[saved_parents[*e as usize]].clone();
if tot > val || tot == val && *e < idx {
return (*e, tot);
}
(idx, val)
};
let (ans, _) = initial
.iter()
.filter(|e| initial_component_freq[sets.find(**e as usize)] <= 1)
.fold((-1, -1), update_best);
if ans == -1 {
*initial.iter().min().unwrap()
} else {
ans
}
}
}