- 尽量减少恶意软件的传播
在节点网络中,只有当 graph[i][j] = 1 时,每个节点 i 能够直接连接到另一个节点 j。
一些节点 initial 最初被恶意软件感染。只要两个节点直接连接,且其中至少一个节点受到恶意软件的感染,那么两个节点都将被恶意软件感染。这种恶意软件的传播将继续,直到没有更多的节点可以被这种方式感染。
假设 M(initial) 是在恶意软件停止传播之后,整个网络中感染恶意软件的最终节点数。
如果从初始列表中移除某一节点能够最小化 M(initial), 返回该节点。如果有多个节点满足条件,就返回索引最小的节点。
请注意,如果某个节点已从受感染节点的列表 initial 中删除,它以后可能仍然因恶意软件传播而受到感染。
示例 1:
输入:graph = [[1,1,0],[1,1,0],[0,0,1]], initial = [0,1]
输出:0
示例 2:
输入:graph = [[1,0,0],[0,1,0],[0,0,1]], initial = [0,2]
输出:0
示例 3:
输入:graph = [[1,1,1],[1,1,1],[1,1,1]], initial = [1,2]
输出:1
提示:
1 < graph.length = graph[0].length <= 300
0 <= graph[i][j] == graph[j][i] <= 1
graph[i][i] == 1
1 <= initial.length < graph.length
0 <= initial[i] < graph.length
题解
真心无语这个题目,很让人误解,一开始各种错,后来看了别人的评论才知道是题意误解了,我把题意进行简化如下,通过连接关系可以得到很多子图,子图之间互相不联通,一开始如果一个子图中出现了2个或者以上被感染的电脑,不论删除哪一个都是不行的,因为剩下的那台电脑会继续感染整个子图中的所有电脑,如果恰好某个子图中只有一台电脑被感染,删除这个电脑就是最好的,于是答案是,如果有多个子图只有一台电脑被感染,找到子图数目最大的那个,删除那个子图中被感染的电脑,如果没有任何一个子图只有一台电脑被感染,就找编号最小的那个被感染的电脑ID返回。
用并查集找联通关系。
AC代码
class Solution {
public:
int f[305];
int fin(int x)
{
if(f[x]==x)return x;
else
return f[x]=fin(f[x]);
}
vector<int>team[305];
bool vis[305];
int minMalwareSpread(vector<vector<int>>& graph, vector<int>& initial)
{
for(int i=0;i<graph.size();i++)
f[i]=i;
for(int i=0;i<graph.size();i++)
{
for(int j=0;j<graph[i].size();j++)
{
if(graph[i][j]==1 && i!=j)
{
int fx=fin(i);
int fy=fin(j);
f[fx]=fy;
}
}
}
memset(vis,0,sizeof(vis));
for(int i=0;i<initial.size();i++)
vis[initial[i]]=true;
for(int i=0;i<graph.size();i++)
{
int fx=fin(i);
team[fx].push_back(i);
}
int res=1e9;
int ans=0;
for(int i=0;i<graph.size();i++)
{
if(team[i].size()>0)
{
int sum=0,fin=-1;
for(int j=0;j<team[i].size();j++)
{
if(vis[team[i][j]])
{
//cout<<team[i][j]<<endl;
sum++;
fin=team[i][j];
}
}
//cout<<i<<" "<<sum<<endl;
if(res == 1e9)
{
if(sum>=2)
{
for(int j=0;j<team[i].size();j++)
{
if(vis[team[i][j]])res=min(res,team[i][j]);
}
}
}
if(sum==1)
{
//cout<<fin<<endl;
if(team[i].size()>ans)
{
ans = team[i].size();
res=fin;
}
else if(team[i].size()==ans)
{
res=min(res,fin);
}
}
}
}
return res;
}
};