struct Solution;
struct UnionFind {
parent: Vec<usize>,
n: usize,
}
impl UnionFind {
fn new(n: usize) -> Self {
let parent = (0..n).collect();
UnionFind { parent, n }
}
fn find(&mut self, i: usize) -> usize {
let j = self.parent[i];
if i == j {
i
} else {
let k = self.find(j);
self.parent[i] = k;
k
}
}
fn union(&mut self, mut i: usize, mut j: usize) {
i = self.find(i);
j = self.find(j);
if i != j {
self.parent[i] = j;
self.n -= 1;
}
}
}
impl Solution {
fn min_malware_spread(graph: Vec<Vec<i32>>, initial: Vec<i32>) -> i32 {
let n = graph.len();
let mut uf = UnionFind::new(n);
let mut initial: Vec<usize> = initial.into_iter().map(|i| i as usize).collect();
for i in 0..n {
for j in i + 1..n {
if graph[i][j] == 1 {
uf.union(i, j);
}
}
}
let mut group_size: Vec<usize> = vec![0; n];
for i in 0..n {
group_size[uf.find(i)] += 1;
}
let mut initial_groups: Vec<usize> = vec![0; n];
for &i in initial.iter() {
let gid = uf.find(i as usize);
initial_groups[gid] += 1;
}
initial.sort_unstable();
let mut res = (0, initial[0]);
for i in initial {
let gid = uf.find(i as usize);
if group_size[gid] > res.0 && initial_groups[gid] == 1 {
res = (group_size[gid], i);
}
}
res.1 as i32
}
}
#[test]
fn test() {
let graph = vec_vec_i32![[1, 1, 0], [1, 1, 0], [0, 0, 1]];
let initial = vec![0, 1];
let res = 0;
assert_eq!(Solution::min_malware_spread(graph, initial), res);
let graph = vec_vec_i32![[1, 0, 0], [0, 1, 0], [0, 0, 1]];
let initial = vec![0, 2];
let res = 0;
assert_eq!(Solution::min_malware_spread(graph, initial), res);
let graph = vec_vec_i32![[1, 1, 1], [1, 1, 1], [1, 1, 1]];
let initial = vec![1, 2];
let res = 1;
assert_eq!(Solution::min_malware_spread(graph, initial), res);
}