![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/83e4ee7515e44c4d8a49c6ae5aa821f1.png)
思路:并查集
- 构建并查集:首先,代码创建了一个
UnionFind
类来维护节点之间的连通关系。它使用了并查集的数据结构,其中 p
数组存储每个节点的父节点,而 size
数组存储每个节点所在集合的大小。 - 遍历图并建立连接关系:接下来,代码遍历了给定的图
graph
,并对图中存在连接的节点调用 union
方法,将它们所在的集合合并起来。 - 统计感染节点数:然后,代码统计了每个初始感染节点所在集合的感染节点数量,并更新了最小节点的值。
- 寻找优化的方案:接着,代码再次遍历了初始感染节点数组
initial
,对每个节点进行如下操作:
- 找到该节点所在集合的根节点。
- 如果该集合中只有一个初始感染节点,那么比较该集合的大小和最大感染节点数,更新答案为当前节点和最大感染节点数。
- 返回结果:最后,代码返回了答案,如果没有找到优化的方案,则返回最小节点。
代码:
class Solution {
public int minMalwareSpread(int[][] graph, int[] initial) {
int n = graph.length;
UnionFind uf = new UnionFind(n);
for (int i = 0; i < n; i++) {
for (int j = i+1; j < n; j++) {
if (graph[i][j] == 1) {
uf.union(i, j);
}
}
}
int ans = n;
int min = n;
int max = 0;
int[] count = new int[n];
for (int x : initial) {
count[uf.find(x)]++;
min = Math.min(min, x);
}
for (int x : initial) {
int root = uf.find(x);
if (count[root] == 1) {
int size = uf.size(root);
if (size > max || (size == max && x < ans)) {
ans = x;
max = size;
}
}
}
return ans == n ? min : ans;
}
}
class UnionFind {
private final int[] p;
private final int[] size;
public UnionFind(int n) {
p = new int[n];
size = new int[n];
for (int i = 0; i < n; i++) {
p[i] = i;
size[i] = 1;
}
}
public int find(int x) {
if (p[x] != x) {
p[x] = find(p[x]);
}
return p[x];
}
public boolean union(int a, int b) {
int pa = find(a);
int pb = find(b);
if (pa == pb) {
return false;
}
if (size[pa] > size[pb]) {
p[pb] = pa;
size[pa] += size[pb];
}else {
p[pa] = pb;
size[pb] += size[pa];
}
return true;
}
public int size(int root) {
return size[root];
}
}
点击移步博客主页,欢迎光临~
![偷cyk的图](https://img-blog.csdnimg.cn/d8b810c80cec4359a11ff9c972bd02d3.gif#pic_center)