C语言----尽量减少恶意软件的传播

 该题特考验语文水平,在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 );
}

最后运行结果: 

 

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ftzchina

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值