Skip to content

Commit 7052dc2

Browse files
committed
feat: add solutions to lc problem: No.0928
No.0928.Minimize Malware Spread II
1 parent 089f6f5 commit 7052dc2

File tree

6 files changed

+299
-368
lines changed

6 files changed

+299
-368
lines changed

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

+103-126
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,13 @@
5555

5656
<!-- 这里可写通用的实现逻辑 -->
5757

58-
并查集。
58+
逆向思维并查集。对于本题,先遍历所有未被感染的节点(即不在 initial 列表的节点),构造并查集,并且在集合根节点维护 size,表示当前集合的节点数。
59+
60+
然后找到只被一个 initial 节点感染的集合,求得感染节点数的最小值。
61+
62+
> 被某个 initial 节点感染的集合,节点数越多,若移除此 initial 节点,感染的节点数就越少。
63+
64+
以下是并查集的几个常用模板。
5965

6066
模板 1——朴素并查集:
6167

@@ -114,12 +120,6 @@ p[find(a)] = find(b)
114120
d[find(a)] = distance
115121
```
116122

117-
对于本题,先遍历所有未被感染的节点(即不在 initial 列表的节点),构造并查集,并且在集合根节点维护 size,表示当前集合的节点数。
118-
119-
然后找到只被一个 initial 节点感染的集合,求得感染节点数的最小值。
120-
121-
> 被某个 initial 节点感染的集合,节点数越多,若移除此 initial 节点,感染的节点数就越少。
122-
123123
<!-- tabs:start -->
124124

125125
### **Python3**
@@ -129,56 +129,43 @@ d[find(a)] = distance
129129
```python
130130
class Solution:
131131
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-
136132
def find(x):
137133
if p[x] != x:
138134
p[x] = find(p[x])
139135
return p[x]
140136

137+
def union(a, b):
138+
pa, pb = find(a), find(b)
139+
if pa != pb:
140+
size[pb] += size[pa]
141+
p[pa] = pb
142+
143+
n = len(graph)
144+
p = list(range(n))
145+
size = [1] * n
141146
clean = [True] * n
142147
for i in initial:
143148
clean[i] = False
144-
145149
for i in range(n):
146150
if not clean[i]:
147151
continue
148152
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-
153+
if clean[j] and graph[i][j] == 1:
154+
union(i, j)
158155
cnt = Counter()
159156
mp = {}
160157
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
158+
s = {find(j) for j in range(n) if clean[j] and graph[i][j] == 1}
159+
for root in s:
160+
cnt[root] += 1
169161
mp[i] = s
170162

171-
mx = -1
172-
res = 0
163+
mx, ans = -1, 0
173164
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
165+
t = sum(size[root] for root in s if cnt[root] == 1)
166+
if mx < t or mx == t and i < ans:
167+
mx, ans = t, i
168+
return ans
182169
```
183170

184171
### **Java**
@@ -188,11 +175,12 @@ class Solution:
188175
```java
189176
class Solution {
190177
private int[] p;
178+
private int[] size;
191179

192180
public int minMalwareSpread(int[][] graph, int[] initial) {
193181
int n = graph.length;
194182
p = new int[n];
195-
int[] size = new int[n];
183+
size = new int[n];
196184
for (int i = 0; i < n; ++i) {
197185
p[i] = i;
198186
size[i] = 1;
@@ -207,16 +195,8 @@ class Solution {
207195
continue;
208196
}
209197
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];
198+
if (clean[j] && graph[i][j] == 1) {
199+
union(i, j);
220200
}
221201
}
222202
}
@@ -225,34 +205,31 @@ class Solution {
225205
for (int i : initial) {
226206
Set<Integer> s = new HashSet<>();
227207
for (int j = 0; j < n; ++j) {
228-
if (!clean[j]) {
229-
continue;
230-
}
231-
if (graph[i][j] == 1) {
208+
if (clean[j] && graph[i][j] == 1) {
232209
s.add(find(j));
233210
}
234211
}
235-
for (int e : s) {
236-
cnt[e] += 1;
212+
for (int root : s) {
213+
cnt[root] += 1;
237214
}
238215
mp.put(i, s);
239216
}
240217
int mx = -1;
241-
int res = 0;
218+
int ans = 0;
242219
for (Map.Entry<Integer, Set<Integer>> entry : mp.entrySet()) {
243220
int i = entry.getKey();
244221
int t = 0;
245-
for (int e : entry.getValue()) {
246-
if (cnt[e] == 1) {
247-
t += size[e];
222+
for (int root : entry.getValue()) {
223+
if (cnt[root] == 1) {
224+
t += size[root];
248225
}
249226
}
250-
if (mx < t || (mx == t && i < res)) {
227+
if (mx < t || (mx == t && i < ans)) {
251228
mx = t;
252-
res = i;
229+
ans = i;
253230
}
254231
}
255-
return res;
232+
return ans;
256233
}
257234

258235
private int find(int x) {
@@ -261,6 +238,15 @@ class Solution {
261238
}
262239
return p[x];
263240
}
241+
242+
private void union(int a, int b) {
243+
int pa = find(a);
244+
int pb = find(b);
245+
if (pa != pb) {
246+
size[pb] += size[pa];
247+
p[pa] = pb;
248+
}
249+
}
264250
}
265251
```
266252

@@ -270,100 +256,101 @@ class Solution {
270256
class Solution {
271257
public:
272258
vector<int> p;
259+
vector<int> size;
273260

274261
int minMalwareSpread(vector<vector<int>>& graph, vector<int>& initial) {
275262
int n = graph.size();
276-
vector<int> size(n, 1);
277-
for (int i = 0; i < n; ++i) p.push_back(i);
263+
p.resize(n);
264+
size.resize(n);
265+
for (int i = 0; i < n; ++i) p[i] = i;
266+
fill(size.begin(), size.end(), 1);
278267
vector<bool> clean(n, true);
279268
for (int i : initial) clean[i] = false;
280269
for (int i = 0; i < n; ++i)
281270
{
282271
if (!clean[i]) continue;
283272
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-
}
273+
if (clean[j] && graph[i][j] == 1) merge(i, j);
294274
}
295275
vector<int> cnt(n, 0);
296276
unordered_map<int, unordered_set<int>> mp;
297277
for (int i : initial)
298278
{
299279
unordered_set<int> s;
300280
for (int j = 0; j < n; ++j)
301-
{
302-
if (!clean[j]) continue;
303-
if (graph[i][j]) s.insert(find(j));
304-
}
281+
if (clean[j] && graph[i][j] == 1) s.insert(find(j));
305282
for (int e : s) ++cnt[e];
306283
mp[i] = s;
307284
}
308-
int mx = -1;
309-
int res = 0;
310-
for (auto item : mp)
285+
int mx = -1, ans = 0;
286+
for (auto& [i, s] : mp)
311287
{
312-
int i = item.first;
313288
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))
289+
for (int root : s)
290+
if (cnt[root] == 1)
291+
t += size[root];
292+
if (mx < t || (mx == t && i < ans))
319293
{
320294
mx = t;
321-
res = i;
295+
ans = i;
322296
}
323297
}
324-
return res;
298+
return ans;
325299
}
326300

327301
int find(int x) {
328302
if (p[x] != x) p[x] = find(p[x]);
329303
return p[x];
330304
}
305+
306+
void merge(int a, int b) {
307+
int pa = find(a), pb = find(b);
308+
if (pa != pb)
309+
{
310+
size[pb] += size[pa];
311+
p[pa] = pb;
312+
}
313+
}
331314
};
332315
```
333316
334317
### **Go**
335318
336319
```go
337-
var p []int
338-
339320
func minMalwareSpread(graph [][]int, initial []int) int {
340321
n := len(graph)
341-
p = make([]int, n)
322+
p := make([]int, n)
342323
size := make([]int, n)
343324
clean := make([]bool, n)
344325
for i := 0; i < n; i++ {
345-
p[i] = i
346-
size[i] = 1
347-
clean[i] = true
326+
p[i], size[i], clean[i] = i, 1, true
348327
}
349328
for _, i := range initial {
350329
clean[i] = false
351330
}
331+
332+
var find func(x int) int
333+
find = func(x int) int {
334+
if p[x] != x {
335+
p[x] = find(p[x])
336+
}
337+
return p[x]
338+
}
339+
union := func(a, b int) {
340+
pa, pb := find(a), find(b)
341+
if pa != pb {
342+
size[pb] += size[pa]
343+
p[pa] = pb
344+
}
345+
}
346+
352347
for i := 0; i < n; i++ {
353348
if !clean[i] {
354349
continue
355350
}
356351
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]
352+
if clean[j] && graph[i][j] == 1 {
353+
union(i, j)
367354
}
368355
}
369356
}
@@ -372,38 +359,28 @@ func minMalwareSpread(graph [][]int, initial []int) int {
372359
for _, i := range initial {
373360
s := make(map[int]bool)
374361
for j := 0; j < n; j++ {
375-
if !clean[j] {
376-
continue
377-
}
378-
if graph[i][j] == 1 {
362+
if clean[j] && graph[i][j] == 1 {
379363
s[find(j)] = true
380364
}
381365
}
382-
for e, _ := range s {
383-
cnt[e]++
366+
for root, _ := range s {
367+
cnt[root]++
384368
}
385369
mp[i] = s
386370
}
387-
mx, res := -1, 0
371+
mx, ans := -1, 0
388372
for i, s := range mp {
389373
t := 0
390-
for e, _ := range s {
391-
if cnt[e] == 1 {
392-
t += size[e]
374+
for root, _ := range s {
375+
if cnt[root] == 1 {
376+
t += size[root]
393377
}
394378
}
395-
if mx < t || (mx == t && i < res) {
396-
mx, res = t, i
379+
if mx < t || (mx == t && i < ans) {
380+
mx, ans = t, i
397381
}
398382
}
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]
383+
return ans
407384
}
408385
```
409386

0 commit comments

Comments
 (0)