华为OD机试真题---服务器广播

news2025/1/6 21:38:09

华为OD机试中的“服务器广播”题目是一个经典的算法问题,通常涉及图论和连通分量的概念。以下是对该题目的详细解析:

一、题目描述

服务器之间可以通过网络进行连接,连接方式包括直接相连和间接连接。给出一个N×N的数组(矩阵),代表N个服务器,matrix[i][j] == 1表示服务器i和服务器j直接连接,matrix[i][j] != 1表示服务器i和服务器j不直接连接。matrix[i][i] == 1,即服务器自己和自己直接连接。matrix[i][j] == matrix[j][i],即连接关系是对称的。

现在要求计算,最少需要向几台服务器发送广播,才能确保所有服务器都能接收到广播。广播可以在直接连接或间接连接的服务器之间传播。

二、输入描述

输入为N行,每行有N个数字,为0或1,由空格分隔,构成N*N的数组,N的范围为 1<=N<=50。

三、输出描述

输出一个数字,为需要广播的服务器数量。

示例 1
输入:
3
1 1 0
1 1 1
0 1 1
输出:
1

解释:在这个例子中,服务器0和服务器1直接连接,服务器1和服务器2直接连接,因此服务器0和服务器2间接连接。只需要向其中任意一台服务器发送广播,其他服务器都能接收到。

示例 2
输入
3
1 0 0
0 1 0
0 0 1
输出
3

说明:3台服务器互不连接,所以需要分别广播这3台服务器。

示例 3
输入
2
1 1
1 1
输出
1

说明: 2台服务器相互连接,所以只需要广播其中一台服务器。

四、解题思路

  1. 图论建模:将服务器之间的连接关系看作一个图,服务器是图的节点,连接关系是图的边。问题转化为求图中的连通分量个数。
  2. 遍历连通分量:使用深度优先搜索(DFS)或广度优先搜索(BFS)遍历图,找到所有的连通分量。
  3. 计算广播服务器数量:连通分量的个数即为需要广播的服务器数量。因为每个连通分量中的服务器都可以通过广播相互传播信息,所以只需要在每个连通分量中选择一个服务器进行广播即可。
  4. 并查集:可以使用并查集实现,并查集(Union-Find)是一种用于处理一些不交集的合并及查询问题的数据结构,它可以高效地解决连通性问题。在“服务器广播”问题中,我们可以使用并查集来找出所有的连通分量,从而确定需要广播的最少服务器数量。

五、代码实现(DFS)

import java.util.Scanner;

public class ServerBroadcast {
   
    /**
     * 使用深度优先搜索(DFS)遍历图中的节点
     * 该方法主要用于找出图中所有相互连通的节点
     * 
     * @param matrix 代表图的邻接矩阵,matrix[i][j]为1表示节点i和节点j之间有直接连接,为0表示无直接连接
     * @param visited 一个布尔数组,用于记录图中各节点的访问状态,visited[i]为true表示节点i已被访问
     * @param node 当前访问的节点编号,从该节点开始进行深度优先搜索
     */
    private static void dfs(int[][] matrix, boolean[] visited, int node) {
        // 标记当前节点为已访问
        visited[node] = true;
        // 遍历图中所有节点
        for (int i = 0; i < matrix.length; i++) {
            // 检查当前节点与节点i是否有连接,且节点i未被访问过
            if (matrix[node][i] == 1 && !visited[i]) {
                // 递归调用dfs方法,继续深度优先搜索节点i
                dfs(matrix, visited, i);
            }
        }
    }


    /**
     * 该方法通过深度优先搜索(DFS)来计算在给定的矩阵中需要广播的服务器数量
     * 每个服务器可以与其直接相连的服务器共享广播,因此形成一个连通分量
     * 该方法旨在找出有多少个这样的连通分量,每个连通分量只需一个服务器进行广播
     *
     * @param matrix 一个二维数组,表示服务器之间的连接关系矩阵
     *               matrix[i][j] == 1 表示服务器i和服务器j之间有直接连接,否则没有
     * @return 广播服务器的数量,即矩阵中连通分量的数量
     */
    public static int countBroadcastServers(int[][] matrix) {
        // 矩阵的长度,即服务器的数量
        int n = matrix.length;
        // 一个布尔数组,用于标记服务器是否已经被访问过
        boolean[] visited = new boolean[n];
        // 初始化广播服务器的数量为0
        int broadcastCount = 0;
    
        // 遍历每个服务器
        for (int i = 0; i < n; i++) {
            // 如果当前服务器尚未被访问过
            if (!visited[i]) {
                // 从当前服务器开始进行深度优先搜索,并将搜索过程中访问到的所有服务器标记为已访问
                dfs(matrix, visited, i);
                // 每完成一次深度优先搜索,表示找到了一个新的连通分量,广播服务器数量加1
                broadcastCount++;
            }
        }
    
        // 返回广播服务器的数量
        return broadcastCount;
    }

    /**
     * 主函数入口
     * 该函数读取输入的服务器数量及它们之间的连接情况,计算并输出需要广播的服务器最小数量
     * @param args 命令行参数
     */
    public static void main(String[] args) {
        // 创建Scanner对象以读取输入数据
        Scanner scanner = new Scanner(System.in);
    
        // 读取服务器数量
        int n = scanner.nextInt();
        // 消耗换行符
        scanner.nextLine();
    
        // 初始化矩阵
        int[][] matrix = new int[n][n];
    
        // 读取矩阵数据
        for (int i = 0; i < n; i++) {
            // 分割输入行以获取矩阵每一行的数据
            String[] line = scanner.nextLine().split(" ");
            for (int j = 0; j < n; j++) {
                // 将字符串数据转换为整数并填充到矩阵中
                matrix[i][j] = Integer.parseInt(line[j]);
            }
        }
    
        // 计算并输出需要广播的服务器数量
        int result = countBroadcastServers(matrix);
        System.out.println(result);
    
        // 关闭Scanner对象
        scanner.close();
    }
}
代码解释:
  1. DFS方法dfs方法接受一个二维数组(矩阵)matrix、一个布尔数组visited(用于记录节点是否被访问过)和一个当前节点node作为参数。它递归地访问所有与当前节点直接相连的未访问节点。

  2. 计算广播服务器数量的方法countBroadcastServers方法接受一个二维数组(矩阵)matrix作为参数,并返回需要广播的服务器数量。它使用一个布尔数组visited来跟踪哪些服务器已经被访问过,并初始化广播计数器broadcastCount为0。然后,它遍历所有服务器节点,对每个未访问的节点调用dfs方法,并将广播计数器增加1。

  3. 主方法main方法读取用户输入,包括服务器数量和矩阵数据,然后调用countBroadcastServers方法计算需要广播的服务器数量,并输出结果。

六、代码实现(并查集)

import java.util.Scanner;

public class ServerBroadcastUnionFind {
    // 并查集类
    static class UnionFind {
        private int[] parent;

        // 初始化并查集
        public UnionFind(int n) {
            parent = new int[n];
            for (int i = 0; i < n; i++) {
                parent[i] = i; // 初始化时,每个节点都是独立的集合,父节点指向自己
            }
        }

        // 查找根节点(路径压缩)
        public int find(int x) {
            if (parent[x] != x) {
                parent[x] = find(parent[x]); // 路径压缩,直接连接到根节点
            }
            return parent[x];
        }

        // 合并两个集合
        public void union(int x, int y) {
            int rootX = find(x);
            int rootY = find(y);
            if (rootX != rootY) {
                parent[rootX] = rootY; // 将一个集合的根节点指向另一个集合的根节点,从而合并两个集合
            }
        }

        // 获取连通分量的数量
        public int countComponents() {
            int count = 0;
            for (int i = 0; i < parent.length; i++) {
                if (find(i) == i) { // 如果节点自己是根节点,说明是一个新的连通分量
                    count++;
                }
            }
            return count;
        }
    }

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        // 读取服务器数量
        int n = scanner.nextInt();
        scanner.nextLine(); // 消耗换行符

        // 初始化并查集
        UnionFind uf = new UnionFind(n);

        // 读取矩阵数据并合并集合
        for (int i = 0; i < n; i++) {
            String[] line = scanner.nextLine().split(" ");
            for (int j = 0; j < n; j++) {
                if (i != j && Integer.parseInt(line[j]) == 1) { // 注意i != j,避免将节点与自己合并
                    uf.union(i, j);
                }
            }
        }

        // 计算并输出需要广播的服务器数量(即连通分量的数量)
        int result = uf.countComponents();
        System.out.println(result);

        scanner.close();
    }
}
代码解释:
  1. 并查集类UnionFind类实现了并查集的基本功能,包括初始化、查找根节点、合并集合和计算连通分量的数量。

  2. 初始化并查集:在main方法中,我们首先读取服务器数量n,然后创建一个大小为n的并查集。

  3. 读取矩阵数据并合并集合:我们遍历矩阵,对于每个matrix[i][j] == 1i != j的情况,调用union方法将服务器i和服务器j所属的集合合并。

  4. 计算并输出需要广播的服务器数量:最后,我们调用countComponents方法计算连通分量的数量,并输出结果。这个数量就是需要广播的最少服务器数量。

七、运行示例解析

以下是对ServerBroadcast类及其main方法的详细运行示例解析步骤:

1. 初始化
  • 服务器数量:首先,程序通过Scanner读取服务器数量n,这里是3
  • 矩阵初始化:然后,程序初始化一个n x n的矩阵matrix,用于表示服务器之间的连接关系。
2. 输入矩阵数据
  • 用户输入矩阵的每一行数据,这里输入的是:
    1 0 0
    0 1 0
    0 0 1
    
  • 程序将这些数据解析为整数,并填充到matrix中。填充后的矩阵表示如下:
    matrix[0][0] = 1, matrix[0][1] = 0, matrix[0][2] = 0
    matrix[1][0] = 0, matrix[1][1] = 1, matrix[1][2] = 0
    matrix[2][0] = 0, matrix[2][1] = 0, matrix[2][2] = 1
    
3. 深度优先搜索(DFS)准备
  • 创建一个布尔数组visited,长度为n,用于记录每个服务器是否已被访问。初始时,所有服务器都未被访问,因此visited数组的所有元素都设置为false
4. 执行DFS并计算连通分量
  • 程序遍历每个服务器(即遍历matrix的每一行和每一列),并对每个未访问的服务器执行DFS。
  • 对于第一个服务器(索引为0),由于它未被访问,程序从它开始进行DFS:
    • 标记服务器0为已访问。
    • 检查服务器0与所有其他服务器的连接关系:
      • 服务器0与服务器1无连接(matrix[0][1] = 0),因此不继续搜索。
      • 服务器0与服务器2无连接(matrix[0][2] = 0),因此不继续搜索。
    • 由于没有进一步的连接,DFS结束,但找到了一个新的连通分量(只包含服务器0)。
  • 接下来,程序检查服务器1(索引为1),它也未被访问:
    • 标记服务器1为已访问。
    • 检查服务器1与所有其他服务器的连接关系:
      • 服务器1与服务器0无连接(因为0已被访问过,所以这里实际上不会继续搜索,但逻辑上它们无直接连接)。
      • 服务器1与服务器2无连接(matrix[1][2] = 0),因此不继续搜索。
    • 同样,DFS结束,找到了另一个新的连通分量(只包含服务器1)。
  • 最后,程序检查服务器2(索引为2),它同样未被访问:
    • 标记服务器2为已访问。
    • 检查服务器2与所有其他服务器的连接关系,但发现都没有直接连接(或者已经被访问过)。
    • DFS结束,找到了最后一个新的连通分量(只包含服务器2)。
5. 计算结果
  • 每次DFS完成后,连通分量的数量(即需要广播的服务器数量)增加1
  • 在这个例子中,有三个独立的连通分量(每个服务器各自为一个分量),因此broadcastCount最终为3
6. 输出结果
  • 程序输出需要广播的服务器数量,这里是3
总结

对于输入的矩阵:

1 0 0
0 1 0
0 0 1

每个服务器都各自独立,没有服务器之间是直接连通的。因此,需要三个服务器来进行广播,以确保所有服务器都能接收到信息。

八、注意事项

  1. 输入验证:在实际应用中,需要对输入进行验证,确保输入的矩阵是合法的N×N矩阵,且元素是0或1。
  2. 性能优化:对于大规模的输入,可以考虑使用更高效的数据结构和算法来优化性能。例如,可以使用邻接表来表示图,以减少空间复杂度。
  3. 边界情况:需要注意处理边界情况,例如当N为1时,只需要向唯一的一台服务器发送广播即可。

综上所述,华为OD机试中的“服务器广播”题目是一个典型的图论问题,可以通过遍历连通分量来解决。掌握深度优先搜索或广度优先搜索等图论算法是解决这类问题的关键。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2271230.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

开源存储详解-分布式存储与ceph

ceph体系结构 rados&#xff1a;reliable, autonomous, distributed object storage, rados rados采用c开发 对象存储 ceph严格意义讲只提供对象存储能力&#xff0c;ceph的块存储能力实际是基于对象存储库librados的rbd 对象存储特点 对象存储采用put/get/delete&#xf…

Midjourney Imagine API 使用

Midjourney Imagine API 申请及使用 Midjourney 是一款非常强大的 AI 绘图工具&#xff0c;只要输入关键字&#xff0c;就能在短短一两分钟生成十分精美的图像。Midjourney 以其出色的绘图能力在业界独树一帜&#xff0c;如今&#xff0c;Midjourney 早已在各个行业和领域广泛…

docker从下载到Python项目打包到容器中运行(解决下拉超时问题)

docker安装&#xff08;如果第一步或者第二步没有成功&#xff0c;说明是你的镜像源有问题&#xff0c;私聊我获取镜像源&#xff09;镜像位置_/etc/yum.repos.d/CentOS-Base.repo sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/dock…

运算指令(PLC)

加 ADD 减 SUB 乘 MUL 除 DIV 浮点运算 整数运算

Linux高级--3.2.5 “外挂式”死锁监测设计

一、生活中“死锁”的场景 三个人&#xff0c;甲乙丙&#xff0c; 甲借了丙的钱&#xff0c;丙借了乙的钱&#xff0c;乙借了甲的钱。 甲找乙还钱&#xff0c;乙说&#xff1a;“别人还我 我就还你 ”&#xff0c;甲说&#xff1a;“好&#xff0c;那我等你” 乙找丙还钱&am…

图像去雾 | 基于Matlab的图像去雾系统(四种方法)

图像去雾 | 基于Matlab的图像去雾系统&#xff08;四种方法&#xff09; 目录 图像去雾 | 基于Matlab的图像去雾系统&#xff08;四种方法&#xff09;效果一览基本介绍程序设计参考资料 效果一览 基本介绍 基于Matlab的图像去雾系统&#xff08;四种方法&#xff09; 关于图像…

解决Vue中设置el-select的高度不生效问题

el-select是Element UI框架中的一个选择器组件&#xff0c;它允许用户从多个选项中选择一个或多个项目。但这里确存在一个小坑&#xff0c;我们可以看到直接修改el-select的高度是无法生效的 <template><div id"login"><el-select v-model"role…

嵌入式驱动开发详解8(阻塞/非阻塞/异步通信)

文章目录 前言阻塞非阻塞异步通知后续 前言 首先来回顾一下“中断”&#xff0c;中断是处理器提供的一种异步机制&#xff0c;我们配置好中断以后就 可以让处理器去处理其他的事情了&#xff0c;当中断发生以后会触发我们事先设置好的中断服务函数&#xff0c; 在中断服务函数…

人工智能之数学基础:向量内积以及应用

本文重点 向量的点积(Dot Product),又称数量积(Scalar Product)或内积,是线性代数中的一个重要概念。它接受两个向量作为输入,并返回一个实数作为输出。点积不仅在数学和物理学中有广泛应用,而且在人工智能领域也扮演着重要角色。 内积 在数学上,向量x和向量y的内积…

集线器,交换机,路由器,mac地址和ip地址知识记录总结

一篇很不错的视频简介 基本功能 从使用方面来说&#xff0c;都是为了网络传输的标识&#xff0c;和机器确定访问对象 集线器、交换机和路由器 常听到路由器和集线器&#xff0c;下面是区别&#xff1a; 集线器 集线器&#xff1a;一个简单的物理扩展接口数量的物理硬件。…

linux 逻辑卷挂盘

1.输入 sudo-i 转到root账号下。 2. 输入root密码后登录&#xff0c;输入parted -l &#xff0c;发现与以前的挂盘不一样&#xff0c;未挂的盘与系统盘在一起&#xff0c;都是/dev/vda里。 2.输入 lsblkr,查看逻辑分区的设备名称 3. 新增目录 mkdir /data 4. 尝试直接将逻辑分…

python23-常用的第三方库01:request模块-爬虫

requests 模块是 Python 中的一个第三方库&#xff0c;用于发送 HTTP 请求。 它提供了一个简单且直观的 API&#xff0c;使得发送网络请求和解析响应变得非常容易。requests 模块支持各种 HTTP 方法&#xff0c;如 GET、POST、PUT、DELETE 等&#xff0c;并且具有处理 cookies…

解释一下:运放的输入失调电流

输入失调电流 首先看基础部分:这就是同相比例放大器 按照理论计算,输入VIN=0时,输出VOUT应为0,对吧 仿真与理论差距较大,有200多毫伏的偏差,这就是输入偏置电流IBIAS引起的,接着看它的定义 同向和反向输入电流的平均值,也就是Ib1、Ib2求平均,即(Ib1+Ib2)/2 按照下面…

常规继承类对象大小

这个相对简单&#xff0c;只需要考虑类对象大小的累加和内存对齐 #include<iostream> using namespace std;class Base { public:int ma;int mb;char mc; };class Derive :public Base { public:int md; };class Derive2 :public Derive { public:int me; };int main() …

Scrum中敏捷项目经理(Scrum Master)扮演什么角色?

敏捷开发模式已经逐渐被主流的软件研发团队所接受&#xff0c;其中Scrum是最具代表性的敏捷方法之一。Scrum框架中有三个核心角色&#xff1a;Product Owner&#xff08;PO&#xff09;、Scrum Master&#xff08;SM&#xff09;和Development Team&#xff08;DT&#xff09;。…

[网络安全]数据安全领域关键技术总结

去标识计算技术 概念 去标识计算 (Differential Privacy) 是一种数据隐私保护技术&#xff0c;它可以在不暴露个人敏感信息的前提下进行统计分析&#xff0c;并保证对隐私的泄露控制在可承受的范围之内。 底层逻辑 基于差分隐私的去标识计算是指在计算处理中采用一些差分隐私…

手机租赁平台开发实用指南与市场趋势分析

内容概要 在当今快速变化的科技时代&#xff0c;手机租赁平台的发展如火如荼。随着越来越多的人希望使用最新款的智能手机&#xff0c;但又不愿意承担昂贵的购机成本&#xff0c;手机租赁平台应运而生。这种模式不仅为用户提供了灵活的选择&#xff0c;还为企业创造了新的商机…

【从零开始入门unity游戏开发之——C#篇42】C#补充知识——随机数(Random)、多种方法实现string字符串拼接、语句的简写

文章目录 一、随机数1、Random.Next()生成随机整数示例&#xff1a;生成一个随机整数生成指定范围内的随机整数 2、Random.NextSingle生成随机浮点数示例&#xff1a;生成随机浮点数 3、 生成随机字母或字符示例&#xff1a;生成随机字母示例&#xff1a;生成随机小写字母 二、…

overleaf写学术论文常用语法+注意事项+审阅修订

常用语法 导入常用的宏包 \usepackage{cite} \usepackage{amsmath,amssymb,amsfonts} \usepackage{algorithmic} \usepackage{algorithm} \usepackage{graphicx} \usepackage{subfigure} \usepackage{textcomp} \usepackage{xcolor} \usepackage{lettrine} \usepackage{booktab…

Rabbitmq追问1

如果消费端代码异常&#xff0c;未手动确认&#xff0c;那么这个消息去哪里 2024-12-31 21:19:12 如果消费端代码发生异常&#xff0c;未手动确认&#xff08;ACK&#xff09;的情况下&#xff0c;消息的处理行为取决于消息队列的实现和配置&#xff0c;以下是基于 RabbitMQ …