题目:
928. 尽量减少恶意软件的传播 II
给定一个由 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 {private int nodeId,size;public int minMalwareSpread(int[][] graph, int[] initial) {int n=graph.length;boolean[] vis=new boolean[n];boolean[] isInitial=new boolean[n];int mn=Integer.MAX_VALUE;for(int x:initial){isInitial[x]=true;mn=Math.min(mn,x);}int[] cnt=new int[n];for(int i=0;i<n;i++){if(vis[i]||isInitial[i]){continue;}nodeId=-1;size=0;dfs(i,graph,vis,isInitial);if(nodeId>=0){//只找到一个在initial中的节点//删除节点nodeId可以让size个点不被感染cnt[nodeId]+=size;}}int maxCnt=0;int minNodeId=-1;for(int i=0;i<n;i++){if(cnt[i]>0&&(cnt[i]>maxCnt||cnt[i]==maxCnt&&i<minNodeId)){maxCnt=cnt[i];minNodeId=i;}}return minNodeId<0?mn:minNodeId;}private void dfs(int x,int[][] graph,boolean[] vis,boolean[] isInitial){vis[x]=true;size++;for(int y=0;y<graph.length;y++){if(graph[x][y]==0) continue;if(isInitial[y]){// 按照 924 题的状态机更新 nodeId// 注意避免重复统计,例如上图中的 0 有两条不同路径可以遇到 1if(nodeId!=-2&&nodeId!=y){nodeId=nodeId==-1?y:-2;}}else if(!vis[y]){dfs(y,graph,vis,isInitial);}}}
}