【Leetcode】924. Minimize Malware Spread(代码)

222 阅读1分钟

题目地址:

leetcode.com/problems/mi…

给定一个 n个节点的无向图,以邻接矩阵给出。每个节点代表一个网络中的节点。再给定一个数组A,A[i]表示节点i ii被感染了(下文称A里的点是”感染源“)。当一个节点被感染了,它所在的连通块的所有节点都会被感染。现在允许选取一个“感染源”,将其变为”未感染“。问将哪个节点变为”未感染“可以使得剩余节点的总的被感染节点数量最小。如果有多个答案,则返回编号最小的节点。

image.png

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

public class Solution {
    
    class UnionFind {
    
        int[] parent, size;
        
        public UnionFind(int size) {
            parent = new int[size];
            for (int i = 0; i < size; i++) {
                parent[i] = i;
            }
            
            this.size = new int[size];
            Arrays.fill(this.size, 1);
        }
        
        public int find(int x) {
            if (parent[x] != x) {
                parent[x] = find(parent[x]);
            }
            
            return parent[x];
        }
        
        public void union(int x, int y) {
            int px = find(x), py = find(y);
            if (px == py) {
                return;
            }
            
            parent[px] = py;
            size[py] += size[px];
        }
    }
    
    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);
                }
            }
        }
        
        // 用map存一下每个被感染的连通块里,”感染源“的个数
        Map<Integer, Integer> map = new HashMap<>();
        for (int x : initial) {
            int px = uf.find(x);
            map.put(px, map.getOrDefault(px, 0) + 1);
        }
        
        // maxN存被感染的最大连通块的size
        int maxN = 0, res = -1;
        for (int x : initial) {
            int px = uf.find(x);
            // 如果找到了感染源数是1的连通块,那么就挑一个size最大的连通块
            if (map.get(px) == 1) {
                if (uf.size[px] > maxN) {
                    maxN = uf.size[px];
                    res = x;
                } else if (uf.size[px] == maxN) {
                	// 如果有多个感染源数是1的连通块size一样,
                	// 则按照要求要返回编号最小的感染源头节点
                    res = Math.min(res, x);
                }
            }
        }
        
        // 如果每个连通块的感染源都多于1,那就清洁initial里编号最小的节点
        if (res == -1) {
            res = n;
            for (int x : initial) {
                res = Math.min(res, x);
            }
        }
        
        return res;
    }
}

参考链接:

  1. happygirlzt
  2. (7条消息) 【Leetcode】924. Minimize Malware Spread_edWard的博客-CSDN博客