leedcode 928. 尽量减少恶意软件的传播 II (并查集)
测试链接:https://leetcode.cn/problems/minimize-malware-spread-ii/
思路
设置sz,inflect,virus[](该节点是否属于感染节点),father,cntans[](统计删除该感染节点可以拯救多少节点)
这道题目先使用并查集解决,如果相邻的节点都为正常节点则将其合并,等所有节点合并后考虑感染相邻节点,如果感染节点相邻节点还没有找出过源头,则此时,改感染节点更新为源头,如果这个相邻集合已经有源头了,则说明这个集合存在多个源头,只通过删除一个感染节点无法拯救,所以无需将inflect[i]设置-2(无效状态),我们初始化各自的集合为-1,如果有源头,则设置inflect[i]为感染节点
处理完各自集合的源头节点后开始统计各个感染节点删除后能拯救的节点数,统计完之后,将感染节点升序排序,更新答案,最后输出答案
题解
const int N=500;
class Solution {
public:
int father[N];
int sz[N];
bool virus[N];
int inflect[N];
int n;
int cntans[N];
void build()
{
for(int i=0;i<n;i++)
{
father[i]=i;
sz[i]=1;
inflect[i]=-1;
virus[i]=false;
}
}
int find(int x)
{
return x==father[x]?x:father[x]=find(father[x]);
}
void join(int x,int y)
{
int fx = find(x);
int fy = find(y);
if(fx!=fy)
{
father[fx]=fy;
sz[fy]+=sz[fx];
}
}
int minMalwareSpread(vector<vector<int>>& graph, vector<int>& initial) {
n = graph.size();
build();
for(int i=0;i<initial.size();i++)
{
virus[initial[i]]=true;
}
for(int i=0;i<n;i++)
{
for(int j=0;j<n;j++)
{
if(!virus[i]&&!virus[j]&&graph[i][j]==1)
{
join(i,j);
}
}
}
for(int i=0;i<initial.size();i++)
{
for(int j=0;j<n;j++)
{
if(initial[i]!=j&&!virus[j]&&graph[initial[i]][j])
{
int fn = find(j);
if(inflect[fn]==-1)
{
inflect[fn]=initial[i];
}
else if(inflect[fn]!=-2&&inflect[fn]!=initial[i])
{
inflect[fn]=-2;
}
}
}
}
for(int i=0;i<n;i++)
{
if(i==father[i]&&inflect[i]>=0)
{
cntans[inflect[i]]+=sz[i];
}
}
sort(initial.begin(),initial.end());
int maxans=cntans[initial[0]];
int ans=initial[0];
for(int i=0;i<initial.size();i++)
{
if(maxans<cntans[initial[i]])
{
maxans = cntans[initial[i]];
ans = initial[i];
}
}
return ans;
}
};

浙公网安备 33010602011771号