Skip to content

Commit 4962c02

Browse files
committed
feat: add solutions to lc problem: No.0928.Minimize Malware Spread II
1 parent 1bfb863 commit 4962c02

File tree

21 files changed

+1700
-6
lines changed

21 files changed

+1700
-6
lines changed

solution/0900-0999/0928.Minimize Malware Spread II/README.md

+335-2
Original file line numberDiff line numberDiff line change
@@ -51,27 +51,360 @@
5151
<li><code>0 &lt;= initial[i] &lt; graph.length</code></li>
5252
</ol>
5353

54-
5554
## 解法
5655

5756
<!-- 这里可写通用的实现逻辑 -->
5857

58+
并查集。
59+
60+
模板 1——朴素并查集:
61+
62+
```python
63+
# 初始化,p存储每个点的祖宗节点
64+
p = list(range(n))
65+
66+
# 返回x的祖宗节点
67+
def find(x):
68+
if p[x] != x:
69+
# 路径压缩
70+
p[x] = find(p[x])
71+
return p[x]
72+
73+
# 合并a和b所在的两个集合
74+
p[find(a)] = find(b)
75+
```
76+
77+
模板 2——维护 size 的并查集:
78+
79+
```python
80+
# 初始化,p存储每个点的祖宗节点,size只有当节点是祖宗节点时才有意义,表示祖宗节点所在集合中,点的数量
81+
p = list(range(n))
82+
size = [1] * n
83+
84+
# 返回x的祖宗节点
85+
def find(x):
86+
if p[x] != x:
87+
# 路径压缩
88+
p[x] = find(p[x])
89+
return p[x]
90+
91+
# 合并a和b所在的两个集合
92+
if find(a) != find(b):
93+
size[find(b)] += size[find(a)]
94+
p[find(a)] = find(b)
95+
```
96+
97+
模板 3——维护到祖宗节点距离的并查集:
98+
99+
```python
100+
# 初始化,p存储每个点的祖宗节点,d[x]存储x到p[x]的距离
101+
p = list(range(n))
102+
d = [0] * n
103+
104+
# 返回x的祖宗节点
105+
def find(x):
106+
if p[x] != x:
107+
t = find(p[x])
108+
d[x] += d[p[x]]
109+
p[x] = t
110+
return p[x]
111+
112+
# 合并a和b所在的两个集合
113+
p[find(a)] = find(b)
114+
d[find(a)] = dinstance
115+
```
116+
117+
对于本题,先遍历所有未被感染的节点(即不在 initial 列表的节点),构造并查集,并且在集合根节点维护 size,表示当前集合的节点数。
118+
119+
然后找到只被一个 initial 节点感染的集合,求得感染节点数的最小值。
120+
121+
> 被某个 initial 节点感染的集合,节点数越多,若移除此 initial 节点,感染的节点数就越少。
122+
59123
<!-- tabs:start -->
60124

61125
### **Python3**
62126

63127
<!-- 这里可写当前语言的特殊实现逻辑 -->
64128

65129
```python
66-
130+
class Solution:
131+
def minMalwareSpread(self, graph: List[List[int]], initial: List[int]) -> int:
132+
n = len(graph)
133+
p = list(range(n))
134+
size = [1] * n
135+
136+
def find(x):
137+
if p[x] != x:
138+
p[x] = find(p[x])
139+
return p[x]
140+
141+
clean = [True] * n
142+
for i in initial:
143+
clean[i] = False
144+
145+
for i in range(n):
146+
if not clean[i]:
147+
continue
148+
for j in range(i + 1, n):
149+
if not clean[j]:
150+
continue
151+
if graph[i][j] == 1:
152+
pa, pb = find(i), find(j)
153+
if pa == pb:
154+
continue
155+
p[pa] = pb
156+
size[pb] += size[pa]
157+
158+
cnt = collections.Counter()
159+
mp = {}
160+
for i in initial:
161+
s = set()
162+
for j in range(n):
163+
if not clean[j]:
164+
continue
165+
if graph[i][j] == 1:
166+
s.add(find(j))
167+
for e in s:
168+
cnt[e] += 1
169+
mp[i] = s
170+
171+
mx = -1
172+
res = 0
173+
for i, s in mp.items():
174+
t = 0
175+
for e in s:
176+
if cnt[e] == 1:
177+
t += size[e]
178+
if mx < t or (mx == t and i < res):
179+
mx = t
180+
res = i
181+
return res
67182
```
68183

69184
### **Java**
70185

71186
<!-- 这里可写当前语言的特殊实现逻辑 -->
72187

73188
```java
189+
class Solution {
190+
private int[] p;
191+
192+
public int minMalwareSpread(int[][] graph, int[] initial) {
193+
int n = graph.length;
194+
p = new int[n];
195+
int[] size = new int[n];
196+
for (int i = 0; i < n; ++i) {
197+
p[i] = i;
198+
size[i] = 1;
199+
}
200+
boolean[] clean = new boolean[n];
201+
Arrays.fill(clean, true);
202+
for (int i : initial) {
203+
clean[i] = false;
204+
}
205+
for (int i = 0; i < n; ++i) {
206+
if (!clean[i]) {
207+
continue;
208+
}
209+
for (int j = i + 1; j < n; ++j) {
210+
if (!clean[j]) {
211+
continue;
212+
}
213+
if (graph[i][j] == 1) {
214+
int pa = find(i), pb = find(j);
215+
if (pa == pb) {
216+
continue;
217+
}
218+
p[pa] = pb;
219+
size[pb] += size[pa];
220+
}
221+
}
222+
}
223+
int[] cnt = new int[n];
224+
Map<Integer, Set<Integer>> mp = new HashMap<>();
225+
for (int i : initial) {
226+
Set<Integer> s = new HashSet<>();
227+
for (int j = 0; j < n; ++j) {
228+
if (!clean[j]) {
229+
continue;
230+
}
231+
if (graph[i][j] == 1) {
232+
s.add(find(j));
233+
}
234+
}
235+
for (int e : s) {
236+
cnt[e] += 1;
237+
}
238+
mp.put(i, s);
239+
}
240+
int mx = -1;
241+
int res = 0;
242+
for (Map.Entry<Integer, Set<Integer>> entry : mp.entrySet()) {
243+
int i = entry.getKey();
244+
int t = 0;
245+
for (int e : entry.getValue()) {
246+
if (cnt[e] == 1) {
247+
t += size[e];
248+
}
249+
}
250+
if (mx < t || (mx == t && i < res)) {
251+
mx = t;
252+
res = i;
253+
}
254+
}
255+
return res;
256+
}
257+
258+
private int find(int x) {
259+
if (p[x] != x) {
260+
p[x] = find(p[x]);
261+
}
262+
return p[x];
263+
}
264+
}
265+
```
266+
267+
### **C++**
268+
269+
```cpp
270+
class Solution {
271+
public:
272+
vector<int> p;
273+
274+
int minMalwareSpread(vector<vector<int>>& graph, vector<int>& initial) {
275+
int n = graph.size();
276+
vector<int> size(n, 1);
277+
for (int i = 0; i < n; ++i) p.push_back(i);
278+
vector<bool> clean(n, true);
279+
for (int i : initial) clean[i] = false;
280+
for (int i = 0; i < n; ++i)
281+
{
282+
if (!clean[i]) continue;
283+
for (int j = i + 1; j < n; ++j)
284+
{
285+
if (!clean[j]) continue;
286+
if (graph[i][j])
287+
{
288+
int pa = find(i), pb = find(j);
289+
if (pa == pb) continue;
290+
p[pa] = pb;
291+
size[pb] += size[pa];
292+
}
293+
}
294+
}
295+
vector<int> cnt(n, 0);
296+
unordered_map<int, unordered_set<int>> mp;
297+
for (int i : initial)
298+
{
299+
unordered_set<int> s;
300+
for (int j = 0; j < n; ++j)
301+
{
302+
if (!clean[j]) continue;
303+
if (graph[i][j]) s.insert(find(j));
304+
}
305+
for (int e : s) ++cnt[e];
306+
mp[i] = s;
307+
}
308+
int mx = -1;
309+
int res = 0;
310+
for (auto item : mp)
311+
{
312+
int i = item.first;
313+
int t = 0;
314+
for (int e : item.second)
315+
{
316+
if (cnt[e] == 1) t += size[e];
317+
}
318+
if (mx < t || (mx == t && i < res))
319+
{
320+
mx = t;
321+
res = i;
322+
}
323+
}
324+
return res;
325+
}
326+
327+
int find(int x) {
328+
if (p[x] != x) p[x] = find(p[x]);
329+
return p[x];
330+
}
331+
};
332+
```
74333
334+
### **Go**
335+
336+
```go
337+
var p []int
338+
339+
func minMalwareSpread(graph [][]int, initial []int) int {
340+
n := len(graph)
341+
p = make([]int, n)
342+
size := make([]int, n)
343+
clean := make([]bool, n)
344+
for i := 0; i < n; i++ {
345+
p[i] = i
346+
size[i] = 1
347+
clean[i] = true
348+
}
349+
for _, i := range initial {
350+
clean[i] = false
351+
}
352+
for i := 0; i < n; i++ {
353+
if !clean[i] {
354+
continue
355+
}
356+
for j := i + 1; j < n; j++ {
357+
if !clean[j] {
358+
continue
359+
}
360+
if graph[i][j] == 1 {
361+
pa, pb := find(i), find(j)
362+
if pa == pb {
363+
continue
364+
}
365+
p[pa] = pb
366+
size[pb] += size[pa]
367+
}
368+
}
369+
}
370+
cnt := make([]int, n)
371+
mp := make(map[int]map[int]bool)
372+
for _, i := range initial {
373+
s := make(map[int]bool)
374+
for j := 0; j < n; j++ {
375+
if !clean[j] {
376+
continue
377+
}
378+
if graph[i][j] == 1 {
379+
s[find(j)] = true
380+
}
381+
}
382+
for e, _ := range s {
383+
cnt[e]++
384+
}
385+
mp[i] = s
386+
}
387+
mx, res := -1, 0
388+
for i, s := range mp {
389+
t := 0
390+
for e, _ := range s {
391+
if cnt[e] == 1 {
392+
t += size[e]
393+
}
394+
}
395+
if mx < t || (mx == t && i < res) {
396+
mx, res = t, i
397+
}
398+
}
399+
return res
400+
}
401+
402+
func find(x int) int {
403+
if p[x] != x {
404+
p[x] = find(p[x])
405+
}
406+
return p[x]
407+
}
75408
```
76409

77410
### **...**

0 commit comments

Comments
 (0)