该题特考验语文水平,在leetcode上找到了一个通俗易懂的中文翻译:
/**
* 从初始列表中删除一个节点。如果移除这一节点将最小化 M(initial),则返回该节点
* 解题思路 [阅读理解]
* 1、理解题意:题目描述很不易理解,首先理解输入graph、initial; 输出 求初始列表中的一个节点,移除这一节点将最小化感染
* a. 输入graph表示每个节点与其他节点的联通情况,以题目中示例一举例 graph = [[1,1,0],[1,1,0],[0,0,1]] 图如下图
* nodeId 0 1 2
* ————|————————————
* graph = 0 | 1, 1, 0
* 1 | 1, 1, 0
* 2 | 0, 0, 1
* 表示有三个节点,节点序号分别为 0,1,2.在节点网络中,只有当 graph[i][j] = 1 时,每个节点 i 能够直接连接到另一个节点 j
* 比如 0号节点可以与 1、2号节点有联通关系,那么 0 号节点与 1 号节点联通则可以表示为 graph[0][1] = 1;
* 0 号节点与 2 号节点不联通则可以表示为 graph[0][2] = 0;
* 节点自身与自身是联通的,也就是图中 graph[0][0] == graph[1][1] == graph[2][2] == 1
* 那么 graph 画图表示为下图, 0 与 1 相连, 没有节点与 2 相连
* 0
* /
* 1 2
* b. 输入initial表示初始被感染的节点,以题目中示例一举例 initial = [0,1] 表示一开始 0号节点与1号节点被感染了
* c. 输出 求初始列表中的一个节点,移除这一节点将最小化感染,注意这里“移除”的真正含义是,把该节点设置为未感染状态,
* 以题目中示例一举例,初始状态0、1被感染,那么我们不论移除0还是移除1,两个节点都会被感染,因为0 和 1 是联通的,移除一个后会被另一个重新传染,
* 要注意题目中最后一句话,“某个节点已从受感染节点的列表 initial 中删除,它以后可能仍然因恶意软件传播而受到感染。”
* d. 题目中其他条件理解,“如果有多个节点满足条件,就返回索引最小的节点”,还是以题目中示例一举例,我们知道从 输入initial
* 初始状态0、1被感染,那么我们不论移除0还是移除1,两个节点都会被感染
* 也就是移除 0 后感染的节点为 0(被1传染),1
* 也就是移除 1 后感染的节点为 0,1(被0传染)
* 这种情况下,我们直接返回 索引最小的节点 0,注意这儿的索引只的是节点的索引
* 上述就是对题意的理解,搞清楚题意后再去看官方解题思路便豁然开朗
*
*
* @param graph 节点网络
* @param initial 最初被恶意软件感染的节点
* @return 将最小化 M(initial)的节点
*/
读懂题意后,再解题就有思路了,本题采用并查集来搞定
1,按照并查集的套路建立好节点的关系
2,对initial数组中的每个节点,在parent中查找该节点所在的子图有多少个节点,记录每次节点查找的节点数,如果节点数大于之前记录的最大MAX,并且没有同一子图中没有两个感染的节点,则记录该索引,最后比较索引所在的节点,返回最小的节点
#define MAXSIZE 301
int parent[MAXSIZE];
int Find(int a)
{
if(parent[a] == a)
return a;
return parent[a] = Find(parent[a]);
}
void unioon(int i, int j)
{
int fi = Find(i);
int fj = Find(j);
if(fi != fj)
parent[fi] = fj;
return;
}
int getNode(int graphSize, int* initial, int initialSize )
{
int count = 0;
int max = 0;
int i,j;
int node = 1000;
//对initial数组中的每个节点,在parent中查找该节点所在的子图有多少个节点
//记录每次节点查找的节点数,如果节点数大于之前记录的最大MAX,并且没有同一子图中没有两个感染的节点,则记录该索引
//最后比较索引所在的节点,返回最小的节点
for(i=0; i<initialSize; i++)
{
count = 0;
for(j=0; j<graphSize; j++)
{
if(parent[initial[i]] == parent[j])
count++;
}
for(j=0; j<initialSize; j++)
{
if(i!=j && parent[initial[i]] == parent[initial[j]])
{
count = 0;
break;
}
}
if(count > max)
{
max = count;
node = initial[i];
}
else if(count == max && node > initial[i])
{
node = initial[i];
}
}
return node;
}
int minMalwareSpread(int** graph, int graphSize, int* graphColSize, int* initial, int initialSize)
{
int i,j;
//初始化parent数组,每个节点的父节点初始化为自己
for(i=0; i<graphSize; i++)
parent[i] = i;
for(i=0; i<graphSize; i++)
{
for(j=i+1; j<graphSize; j++)
{
if(graph[i][j] == 1)
unioon(i,j);
}
}
for(i=0; i<graphSize; i++)
{
Find(i);
}
return getNode(graphSize, initial, initialSize );
}
最后运行结果: