924. Minimize Malware Spread #
题目 #
In a network of nodes, each node i
is directly connected to another node j
if and only if graph[i][j] = 1
.
Some nodes initial
are initially infected by malware. Whenever two nodes are directly connected and at least one of those two nodes is infected by malware, both nodes will be infected by malware. This spread of malware will continue until no more nodes can be infected in this manner.
Suppose M(initial)
is the final number of nodes infected with malware in the entire network, after the spread of malware stops.
We will remove one node from the initial list. Return the node that if removed, would minimize M(initial)
. If multiple nodes could be removed to minimize M(initial)
, return such a node with the smallest index.
Note that if a node was removed from the initial
list of infected nodes, it may still be infected later as a result of the malware spread.
Example 1:
Input: graph = [[1,1,0],[1,1,0],[0,0,1]], initial = [0,1]
Output: 0
Example 2:
Input: graph = [[1,0,0],[0,1,0],[0,0,1]], initial = [0,2]
Output: 0
Example 3:
Input: graph = [[1,1,1],[1,1,1],[1,1,1]], initial = [1,2]
Output: 1
Note:
1 < graph.length = graph[0].length <= 300
0 <= graph[i][j] == graph[j][i] <= 1
graph[i][i] = 1
1 <= initial.length < graph.length
0 <= initial[i] < graph.length
题目大意 #
在节点网络中,只有当 graph[i][j] = 1 时,每个节点 i 能够直接连接到另一个节点 j。一些节点 initial 最初被恶意软件感染。只要两个节点直接连接,且其中至少一个节点受到恶意软件的感染,那么两个节点都将被恶意软件感染。这种恶意软件的传播将继续,直到没有更多的节点可以被这种方式感染。假设 M(initial) 是在恶意软件停止传播之后,整个网络中感染恶意软件的最终节点数。我们可以从初始列表中删除一个节点。如果移除这一节点将最小化 M(initial), 则返回该节点。如果有多个节点满足条件,就返回索引最小的节点。请注意,如果某个节点已从受感染节点的列表 initial 中删除,它以后可能仍然因恶意软件传播而受到感染。
提示:
- 1 < graph.length = graph[0].length <= 300
- 0 <= graph[i][j] == graph[j][i] <= 1
- graph[i][i] = 1
- 1 <= initial.length < graph.length
- 0 <= initial[i] < graph.length
解题思路 #
- 给出一个节点之间的关系图,如果两个节点是连通的,那么病毒软件就会感染到连通的所有节点。现在如果想移除一个病毒节点,能最大减少感染,请问移除哪个节点?如果多个节点都能减少感染量,优先移除序号偏小的那个节点。
- 这一题一看就是考察的并查集。利用节点的连通关系,把题目中给的所有节点都
union()
起来,然后依次统计每个集合内有多少个点。最后扫描一次 initial 数组,选出这个数组中节点小的并且所在集合节点多,这个节点就是最终答案。
代码 #
package leetcode
import (
"math"
"github.com/halfrost/leetcode-go/template"
)
func minMalwareSpread(graph [][]int, initial []int) int {
if len(initial) == 0 {
return 0
}
uf, maxLen, maxIdx, uniqInitials, compMap := template.UnionFindCount{}, math.MinInt32, -1, map[int]int{}, map[int][]int{}
uf.Init(len(graph))
for i := range graph {
for j := i + 1; j < len(graph); j++ {
if graph[i][j] == 1 {
uf.Union(i, j)
}
}
}
for _, i := range initial {
compMap[uf.Find(i)] = append(compMap[uf.Find(i)], i)
}
for _, v := range compMap {
if len(v) == 1 {
uniqInitials[v[0]] = v[0]
}
}
if len(uniqInitials) == 0 {
smallestIdx := initial[0]
for _, i := range initial {
if i < smallestIdx {
smallestIdx = i
}
}
return smallestIdx
}
for _, i := range initial {
if _, ok := uniqInitials[i]; ok {
size := uf.Count()[uf.Find(i)]
if maxLen < size {
maxLen, maxIdx = size, i
} else if maxLen == size {
if i < maxIdx {
maxIdx = i
}
}
}
}
return maxIdx
}