Python 3 solution, Union Find Solution, easy to follow explanation with comments
\nclass Solution:\n    \n    ## Quick Union Find\n\t## Data Structure for quickly getting connected components of a graph\n    ## Guarantees log(n) time to get_
```\nclass Solution:\n    \n    ## Quick Union Find\n\t## Data Structure for quickly getting connected components of a graph\n    ## Guarantees log(n) time to get_component_id, join, is_connected, get_size\n    class UnionFind:\n        \n        def __init__(self, size):\n            self.size = size\n            self.id = [i for i in range(size)]\n            self.component_size = [1 for i in range(size)]\n        \n        ## get the component id \n        def get_component_id(self,node_id):\n            curr_id = node_id\n            while (self.id[node_id] != node_id):\n                node_id = self.id[node_id] \n            end = node_id\n                \n            ## flatten this structure (not necessary, just an optimization)\n            curr_id = node_id\n            while (self.id[node_id] != node_id):\n                next_node = self.id[node_id] \n                self.id[node_id] = end\n            return end\n        \n        ## are p and q in the same component?\n        def is_connected(self,p,q):\n            return self.get_component_id(p) == self.get_component_id(q)\n        \n        ## combined the two components p and q are in\n        def join(self, p, q):\n            root_p = self.get_component_id(p)\n            root_q = self.get_component_id(q)\n            \n            if self.component_size[root_p] < self.component_size[root_q]:\n                self.join(root_q,root_p)\n                return\n            \n            if not self.is_connected(root_p,root_q):\n            \n                self.id[root_q] = root_p\n                self.component_size[root_p] += self.component_size[root_q]\n        \n        ## what is the size of the component p is in?\n        def get_size(self,p):\n            return self.component_size[self.get_component_id(p)]\n        \n    \n    def minMalwareSpread(self, graph: List[List[int]], initial: List[int]) -> int:\n        n = len(graph)\n        initial_set = set(initial)\n        \n        ## create connected components of non-malware nodes\n        uf = Solution.UnionFind(n)\n        for i in range(n):\n            if i not in initial_set:\n                for j in range(n):\n                    if graph[i][j] and j not in initial_set:\n                        uf.join(i,j)\n        \n        ## for each component, get a set of all malware nodes that connect directly to it\n        components_to_malware = defaultdict(set)\n        for i in initial_set:\n            for j in range(n):\n                if graph[i][j] == 1 and j not in initial_set:\n                    components_to_malware[uf.get_component_id(j)].add(i)\n        \n        ## for each component if it is connected to:\n        ##      0 malware nodes, then they will never be infected, no matter what is removed\n        ##      1 malware node,  then they will not be infected if that node is removed, otherwise they will be\n        ##      2 malware nodes, they will always be infected, no matter what is removed\n        ## So go through every component, if it connected to only one malware node, add the components size\n        ## to malware_size, which is a dictionary with keys the malware ids and values M(initial) if the id\n        ## is removed.\n        malware_size = defaultdict(int)\n        for i in initial_set:\n            malware_size[i] = 0\n        for component in components_to_malware.keys():\n            if len(components_to_malware[component]) == 1:\n                for malware_id in components_to_malware[component]:\n                    malware_size[malware_id] += uf.get_size(component)\n        \n        ## go through all malware_ids, select the id with greatest size (and smallest id if there is a tie)\n        best_id = -1\n        best_size = -1\n        for malware_id in malware_size.keys():\n            if malware_size[malware_id] > best_size or (malware_size[malware_id] == best_size and malware_id < best_id):\n                best_size = malware_size[malware_id]\n                best_id = malware_id\n        return best_id\n                \n        \n        \n        ```
['Union Find', 'Python']