Minimize Malware Spread

Remove one initially infected node to minimize total infections — DSU on the network.

Hard
Time O(N^2 * α) Space O(N)
LeetCode
7 min read
union-find graph

Problem#

Given an undirected graph (adjacency matrix graph) and a list of initially infected nodes initial, remove exactly one node from initial to minimize the final number of infected nodes (infection spreads through connected components). Return the chosen node; on tie, return the smallest index.

Examples#

  • graph = [[1,1,0],[1,1,0],[0,0,1]], initial = [0,1]0.
  • graph = [[1,0,0],[0,1,0],[0,0,1]], initial = [0,2]0.

Constraints#

  • n == graph.length, 2 <= n <= 300, 1 <= initial.length <= n.

Hints#

Hint 1
Build components with DSU. A component containing one initial node is “saved” if we remove that node.
Hint 2
A component with >= 2 initial nodes can’t be saved by removing only one — its infection persists.

Approach#

DSU all edges. For each initial node, count how many initial nodes share its component. The savable components are those with exactly one initial node — removing that node saves componentSize infections. Pick the initial node giving the largest saving, breaking ties by smallest index. If no component is single-seeded, return the smallest initial node.

Solution#

Minimize Malware Spread
class Solution {
vector<int> parent, sz;
int find(int x) { while (parent[x] != x) { parent[x] = parent[parent[x]]; x = parent[x]; } return x; }
void unite(int a, int b) {
a = find(a); b = find(b); if (a == b) return;
if (sz[a] < sz[b]) swap(a, b);
parent[b] = a; sz[a] += sz[b];
}
public:
int minMalwareSpread(vector<vector<int>>& graph, vector<int>& initial) {
int n = graph.size();
parent.resize(n); sz.assign(n, 1);
iota(parent.begin(), parent.end(), 0);
for (int i = 0; i < n; ++i)
for (int j = i + 1; j < n; ++j)
if (graph[i][j]) unite(i, j);
unordered_map<int,int> initInRoot;
for (int v : initial) ++initInRoot[find(v)];
sort(initial.begin(), initial.end());
int best = initial[0], bestSave = -1;
for (int v : initial) {
int r = find(v);
int save = (initInRoot[r] == 1) ? sz[r] : 0;
if (save > bestSave) { bestSave = save; best = v; }
}
return best;
}
};

Editorial#

The crucial observation: a component with two or more initial infected nodes still gets fully infected after removing any one of them. Only components with exactly one initial node give a real saving — and that saving equals the component’s size. Sorting initial ascending and breaking ties with strict > makes the smallest-index tiebreak automatic.

Complexity#

  • Time: O(N^2 * α(N)) for the adjacency-matrix scan.
  • Space: O(N).

Concept revision#

Search ESC

Keyboard shortcuts

Shortcuts are disabled while typing in inputs.