leetcode 924

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.1 < graph.length = graph[0].length <= 300
2.0 <= graph[i][j] == graph[j][i] <= 1
3.graph[i][i] = 1
4.1 <= initial.length < graph.length
5.0 <= initial[i] < graph.length
题目意思:现在有一个网络,由邻接矩阵可知其连通性。在网络中,有几个节点被感染,并且会感染与其相连的所有节点。现在从已知的,最初被感染的节点中去除一个,使网络中被感染的节点达到最小,则应该去除哪个节点。
在做题之前,我们可以先考虑图的组成。对于连通图,也就是一个树,如果存在两个及两个以上的初始感染节点,那么只有将被感染的节点全部去除,才能使这颗树不被感染,否则,这颗树的节点将全部感染。由此,可推的非连通图的情况:如果一个连通量中,存在多个被感染的初始节点,那么无论去除哪个初始感染节点,这个连通量都将被感染。所以,要找寻图中的仅有一个初始感染点且连通量所包含的节点数尽可能大。

class Solution {
    
    vector<int> parent;
    int find(int x) {//寻找节点x的根节点
        if(parent[x]==-1)
            return x;
        return find(parent[x]);
    }
    
    void Union(int x, int y) {//对于根节点x和根节点y,x作为y的根节点,x是合并后的根节点
        parent[y]=x;
        parent[x]=-1;
    }
    
public:
    int minMalwareSpread(vector<vector<int>>& graph, vector<int>& initial) {
        int n=graph.size();//图节点个数
        parent.resize(n);//将parent的size置为图的大小
        for(int i=0;i<n;i++)
            parent[i]=-1;//parent中值为1的就是根节点
        unordered_map<int,int> count;
        for(int i=0;i<graph.size();i++)
            count[i]=1;//count初始化,每一个value都是1,代表有一个节点存在
        for(int i=0;i<graph.size();i++) {
            for(int j=i+1;j<graph[i].size();j++) {
                if(graph[i][j]==1) {//说明i和j有连接
                    int parx=find(i);
                    int pary=find(j);
                    if(parx!=pary) {//如果两个根节点不同
                        Union(parx,pary);//合并
                        count[parx]+=count[pary];//两棵树节点个数求和
                    }
                }
            }  
        }
        int ans=INT_MAX;
        for(int i=0;i<initial.size();i++) {//initial.size()是感染病毒节点的个数
            ans=min(ans, initial[i]);//感染节点中值最小的赋值给ans
        }
        int maxi=0;
        unordered_map<int,int> seen;
        for(int i=0;i<initial.size();i++) {
            int par=find(initial[i]);//par是当前感染节点i的根节点
            seen[par]++;//循环结束后根节点par有seen[par]个感染节点
        }
        for(int i=0;i<initial.size();i++) {
            int par=find(initial[i]);
            if(seen[par]==1) {//判断只含有一个感染节点的根节点的树
                if(count[par]>maxi) {
                    maxi=count[par];
                    ans=initial[i];
                }
                else if(count[par]==maxi) {//对于个数相同的情况取index最小
                    ans=min(ans, initial[i]);
                }
            }
        }
        return ans;
    }
};

本题思想主要用到图中的并查集(https://www.cnblogs.com/xzxl/p/7226557.html)
笔记就不在这里展开
时间复杂度O(N^2)
空间复杂度O(N)

猜你喜欢

转载自blog.csdn.net/beizhengren/article/details/88582704