返回介绍

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

发布于 2024-06-17 01:03:33 字数 7605 浏览 0 评论 0 收藏 0

928. 尽量减少恶意软件的传播 II

English Version

题目描述

给定一个由 n 个节点组成的网络,用 n x n 个邻接矩阵 graph 表示。在节点网络中,只有当 graph[i][j] = 1 时,节点 i 能够直接连接到另一个节点 j

一些节点 initial 最初被恶意软件感染。只要两个节点直接连接,且其中至少一个节点受到恶意软件的感染,那么两个节点都将被恶意软件感染。这种恶意软件的传播将继续,直到没有更多的节点可以被这种方式感染。

假设 M(initial) 是在恶意软件停止传播之后,整个网络中感染恶意软件的最终节点数。

我们可以从 initial删除一个节点并完全移除该节点以及从该节点到任何其他节点的任何连接。

请返回移除后能够使 M(initial) 最小化的节点。如果有多个节点满足条件,返回索引 最小的节点

 

    示例 1:

    输入:graph = [[1,1,0],[1,1,0],[0,0,1]], initial = [0,1]
    输出:0
    

    示例 2:

    输入:graph = [[1,1,0],[1,1,1],[0,1,1]], initial = [0,1]
    输出:1
    

    示例 3:

    输入:graph = [[1,1,0,0],[1,1,1,0],[0,1,1,1],[0,0,1,1]], initial = [0,1]
    输出:1
    

     

    提示:

    • n == graph.length
    • n == graph[i].length
    • 2 <= n <= 300
    • graph[i][j] 是 0 或 1.
    • graph[i][j] == graph[j][i]
    • graph[i][i] == 1
    • 1 <= initial.length < n
    • 0 <= initial[i] <= n - 1
    •  initial 中每个整数都不同

    解法

    方法一

    class Solution:
      def minMalwareSpread(self, graph: List[List[int]], initial: List[int]) -> int:
        def find(x):
          if p[x] != x:
            p[x] = find(p[x])
          return p[x]
    
        def union(a, b):
          pa, pb = find(a), find(b)
          if pa != pb:
            size[pb] += size[pa]
            p[pa] = pb
    
        n = len(graph)
        p = list(range(n))
        size = [1] * n
        clean = [True] * n
        for i in initial:
          clean[i] = False
        for i in range(n):
          if not clean[i]:
            continue
          for j in range(i + 1, n):
            if clean[j] and graph[i][j] == 1:
              union(i, j)
        cnt = Counter()
        mp = {}
        for i in initial:
          s = {find(j) for j in range(n) if clean[j] and graph[i][j] == 1}
          for root in s:
            cnt[root] += 1
          mp[i] = s
    
        mx, ans = -1, 0
        for i, s in mp.items():
          t = sum(size[root] for root in s if cnt[root] == 1)
          if mx < t or mx == t and i < ans:
            mx, ans = t, i
        return ans
    
    class Solution {
      private int[] p;
      private int[] size;
    
      public int minMalwareSpread(int[][] graph, int[] initial) {
        int n = graph.length;
        p = new int[n];
        size = new int[n];
        for (int i = 0; i < n; ++i) {
          p[i] = i;
          size[i] = 1;
        }
        boolean[] clean = new boolean[n];
        Arrays.fill(clean, true);
        for (int i : initial) {
          clean[i] = false;
        }
        for (int i = 0; i < n; ++i) {
          if (!clean[i]) {
            continue;
          }
          for (int j = i + 1; j < n; ++j) {
            if (clean[j] && graph[i][j] == 1) {
              union(i, j);
            }
          }
        }
        int[] cnt = new int[n];
        Map<Integer, Set<Integer>> mp = new HashMap<>();
        for (int i : initial) {
          Set<Integer> s = new HashSet<>();
          for (int j = 0; j < n; ++j) {
            if (clean[j] && graph[i][j] == 1) {
              s.add(find(j));
            }
          }
          for (int root : s) {
            cnt[root] += 1;
          }
          mp.put(i, s);
        }
        int mx = -1;
        int ans = 0;
        for (Map.Entry<Integer, Set<Integer>> entry : mp.entrySet()) {
          int i = entry.getKey();
          int t = 0;
          for (int root : entry.getValue()) {
            if (cnt[root] == 1) {
              t += size[root];
            }
          }
          if (mx < t || (mx == t && i < ans)) {
            mx = t;
            ans = i;
          }
        }
        return ans;
      }
    
      private int find(int x) {
        if (p[x] != x) {
          p[x] = find(p[x]);
        }
        return p[x];
      }
    
      private void union(int a, int b) {
        int pa = find(a);
        int pb = find(b);
        if (pa != pb) {
          size[pb] += size[pa];
          p[pa] = pb;
        }
      }
    }
    
    class Solution {
    public:
      vector<int> p;
      vector<int> size;
    
      int minMalwareSpread(vector<vector<int>>& graph, vector<int>& initial) {
        int n = graph.size();
        p.resize(n);
        size.resize(n);
        for (int i = 0; i < n; ++i) p[i] = i;
        fill(size.begin(), size.end(), 1);
        vector<bool> clean(n, true);
        for (int i : initial) clean[i] = false;
        for (int i = 0; i < n; ++i) {
          if (!clean[i]) continue;
          for (int j = i + 1; j < n; ++j)
            if (clean[j] && graph[i][j] == 1) merge(i, j);
        }
        vector<int> cnt(n, 0);
        unordered_map<int, unordered_set<int>> mp;
        for (int i : initial) {
          unordered_set<int> s;
          for (int j = 0; j < n; ++j)
            if (clean[j] && graph[i][j] == 1) s.insert(find(j));
          for (int e : s) ++cnt[e];
          mp[i] = s;
        }
        int mx = -1, ans = 0;
        for (auto& [i, s] : mp) {
          int t = 0;
          for (int root : s)
            if (cnt[root] == 1)
              t += size[root];
          if (mx < t || (mx == t && i < ans)) {
            mx = t;
            ans = i;
          }
        }
        return ans;
      }
    
      int find(int x) {
        if (p[x] != x) p[x] = find(p[x]);
        return p[x];
      }
    
      void merge(int a, int b) {
        int pa = find(a), pb = find(b);
        if (pa != pb) {
          size[pb] += size[pa];
          p[pa] = pb;
        }
      }
    };
    
    func minMalwareSpread(graph [][]int, initial []int) int {
      n := len(graph)
      p := make([]int, n)
      size := make([]int, n)
      clean := make([]bool, n)
      for i := 0; i < n; i++ {
        p[i], size[i], clean[i] = i, 1, true
      }
      for _, i := range initial {
        clean[i] = false
      }
    
      var find func(x int) int
      find = func(x int) int {
        if p[x] != x {
          p[x] = find(p[x])
        }
        return p[x]
      }
      union := func(a, b int) {
        pa, pb := find(a), find(b)
        if pa != pb {
          size[pb] += size[pa]
          p[pa] = pb
        }
      }
    
      for i := 0; i < n; i++ {
        if !clean[i] {
          continue
        }
        for j := i + 1; j < n; j++ {
          if clean[j] && graph[i][j] == 1 {
            union(i, j)
          }
        }
      }
      cnt := make([]int, n)
      mp := make(map[int]map[int]bool)
      for _, i := range initial {
        s := make(map[int]bool)
        for j := 0; j < n; j++ {
          if clean[j] && graph[i][j] == 1 {
            s[find(j)] = true
          }
        }
        for root, _ := range s {
          cnt[root]++
        }
        mp[i] = s
      }
      mx, ans := -1, 0
      for i, s := range mp {
        t := 0
        for root, _ := range s {
          if cnt[root] == 1 {
            t += size[root]
          }
        }
        if mx < t || (mx == t && i < ans) {
          mx, ans = t, i
        }
      }
      return ans
    }
    

    如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

    扫码二维码加入Web技术交流群

    发布评论

    需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
    列表为空,暂无数据
      我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
      原文