服务器广播(牛客网题目,C语言)

标题:服务器广播 | 时间限制:1 秒 | 内存限制:262144K | 语言限制:不限
服务器连接方式包括直接相连,间接连接。A 和 B 直接连接,B 和 C 直接连接,则 A 和 C 间
接连接。直接连接和间接连接都可以发送广播。
给出一个 N*N 数组,代表 N 个服务器,matrix[i][j] == 1,则代表 i 和 j 直接连接;不等于 1
时,代表 i 和 j 不直接连接。matrix[i][i] == 1,即自己和自己直接连接。matrix[i][j] == matrix[j][i]。
计算初始需要给几台服务器广播,才可以使每个服务器都收到广播。
输入描述:
输入为 N 行,每行有 N 个数字,为 0 或 1,由空格分隔,构成 N*N 的数组,N 的范围为
1<=N<=40
输出描述:
输出一个数字,为需要广播的服务器的数量
示例 1
输入
1 0 0
0 1 0
0 0 1
输出
3
说明3 台服务器互不连接,所以需要分别广播这 3 台服务器

代码如下:

*****************************************代码分界线********************************************

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
#include<math.h>
void main()
{
    int martrix[40][40];
    int count=40,i,j,i1,count2=0;
    char ch = ' ';
    for (i = 0; i < count; i++)
    {
        for (j = 0; ch != '\n'; j++)/*题目中不允许先录入N的数值,要根据第一行输入的数字数量进行判断,这里每输入一个数字就打一个空格录入字符ch里面,直到一行输完录入换行符,然后把第一行数字的数量用count记下来*/
        {
            scanf("%d", &martrix[i][j]);
            ch = getchar();
        }
        ch = ' ';/*这里是输入完一行以后要把ch初始化,否则第二行要输入时进不去里面循环无法输入*/
        if (i == 0)/*这里是第一行输入完就把数字数量赋给count,当做外层for循环的条件*/
            count = j;
    }

    for(i=0;i<count;i++)/*这个for循环的作用见下文,概括一下就是把原数组加工一下方便后续是否连通的判断(第一部分)*/
        for (j = 0; j < count; j++)
        {
            if (martrix[i][j] == 1)
            {
                for (i1 = 0; i1 < count; i1++)
                {
                    if (martrix[i1][j] == 1)
                    {
                        martrix[i1][i] = 1;
                        martrix[i][i1] = 1;
                    }
                }
            }
        }
    int judge[40], flag;
    for (i = 0; i < count; i++)/*这个循环是计算需要广播的台数,具体见下文(第二部分)*/
        judge[i] = 0;
    for (i = 0; i < count; i++)
    {
        flag = 0;
        for (j = 0; j < count; j++)
        {
            if (flag == 0 && martrix[i][j] == 1 && judge[j] == 0)
            {
                count2++;
                flag = 1;

            }
            if (martrix[i][j] == 1)
            {
                judge[j] = 1;
            }
        }
    }
    printf("%d", count2);
}

*****************************************代码分界线********************************************

首先来说说第一部分

 for(i=0;i<count;i++)
        for (j = 0; j < count; j++)
        {
            if (martrix[i][j] == 1)
            {
                for (i1 = 0; i1 < count; i1++)
                {
                    if (martrix[i1][j] == 1)
                    {
                        martrix[i1][i] = 1;
                        martrix[i][i1] = 1;
                    }
                }
            }
        }

这个部分就是把间接连接的服务器在矩阵中以直接连接的方式表示出来,方便后续的计算。

举个例子,假如现在录入的数组为:

   A B C D

A 1 0 0 1

B 0 1 1 1

C 0 1 1 0

D 1 1 0 1

ok,可以看到A与D相连,D与B相连,B与C相连,所以实际上ABCD互相直接或间接连接,所以发送广播的时候只需要发一次就够了。那么通过上面那个循环,这个矩阵就会变为:

  A B C D

A 1 1 1 1

B 1 1 1 1

C 1 1 1 1

D 1 1 1 1

大致的做法就是,举个例子,A-D是1,B-D是1,那么A-B和B-A都设置为1。依次循环,所有的元素都进行判断。

ok,那么来到第二部分,如何计算出需要广播的服务器数量。上面的这个加工后的数组很清楚地就能看出,一次就够,但是光看出来不行,计算机要能按逻辑计算出来。为了更好地说明第二部分的作用,这回举另一个例子。

假如原始数组是这样:

  A B C D

A 1 0 1 0

B 0 1 0 1

C 1 0 1 0

D 0 1 0 1

OK,简单解释一下就是AC相连,BD相连。所以显而易见,这个数组经过第一部分的加工以后没有任何变化,还是如上所示。因为没有任何的间接连接。

这时候第二部分开始计算广播的服务器数量。首先我们先弄一个名为judge的数组(judge[4]),初始化以后里面都是0{0,0,0,0},用count2来记录要进行广播的次数,初始化为0,然后一行一行,一个元素一个元素的进行判定。在每行进行判定之前,将flag初始化为0,当在每行的判定中第一次检测到judge中的0被改变为1时count2++,flag变为1,此后在这一行的判定中即使再次将judge中的0改变为1,count2也不再增加。首先是第一行A{1,0,1,0},如果judge数组里面相对应的数字是0但A中不是0的就将其对应改变为1,所以第一行判定完后,judge里面为{1,0,1,0}。judge中有数被改变,所以count2++;

然后是第二行B{0,1,0,1},判定完以后judge中是{1,1,1,1},count2++(此时为2)。

第三行和第四行不再赘述,因为judge中所有数值均已为1,最后得出的结果就是2,即至少需要给两个服务器广播才能使所有的服务器都收到广播。

如果是第一个例子,那么在进行第一行的判定时(A{1,1,1,1})就会使judge变为{1,1,1,1},count2此时为1,由于后续judge中不再有值被改变,所以1即为第一个例子的答案。

下面是在第一个例子的基础上又加了两个节点,验证了一下没啥问题,这两个节点是互通的,结果就是2

 当时在学数据结构的时候记得有个东西叫做连通分量,不过年代久远记不得了,用那个可能更简单,写完这个代码总觉得有捷径比这个简单,不过由于最近状态不好,确实左思右想想不出来。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值