最新华为OD机试
题目描述
服务器连接方式包括直接相连,间接连接。
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
123
输出
3
1
说明
3 台服务器互不连接,所以需要分别广播这 3 台服务器
示例2
输入
1 1
1 1
12
输出
1
1
说明
2 台服务器相互连接,所以只需要广播其中一台服务器
解题思路
这道题可以理解为在一组服务器之间进行广播传播。服务器之间既可以直接相连,也可以通过其他服务器间接相连。题目的目的是计算最少需要对几台服务器进行广播,才能保证所有服务器都能收到广播信号。
题目要点:
-
服务器的直接连接与间接连接:
-
如果服务器
A
和服务器B
直接连接,或者服务器A
可以通过其他服务器间接连接到B
,则广播信号可以通过这些连接传播。 -
如果服务器
A
和服务器B
不存在直接或间接的连接,说明它们属于不同的独立网络,广播信号无法在这些网络间传播。
-
-
矩阵描述:
- 给定的
N*N
矩阵matrix
描述了服务器的连接状态:matrix[i][j] == 1
表示服务器i
和服务器j
直接相连。matrix[i][j] == 0
表示服务器i
和服务器j
之间没有直接连接。matrix[i][i] == 1
,表示每台服务器都和自己直接相连。- 矩阵是对称的,即
matrix[i][j] == matrix[j][i]
,意味着连接是双向的。
- 给定的
-
广播的最小台数:
- 要使每一台服务器都能接收到广播,需要确保每一个相互不连通的服务器组至少有一台服务器接收到初始广播。
- 题目中需要计算最少要对多少台服务器发起广播,才能使所有服务器都能通过直接或间接连接接收到广播。
示例分析:
示例 1:
输入:
1 0 0
0 1 0
0 0 1
123
解释:
- 这 3 台服务器互相之间都没有连接,表示它们是完全独立的 3 个部分。
- 为了使所有服务器都能接收到广播,需要分别对每台服务器进行广播,因此结果是
3
。
示例 2:
输入:
1 1
1 1
12
解释:
- 这 2 台服务器相互直接连接,只需要对其中一台服务器进行广播,信号就会传递到另一台服务器,因此只需要一次广播,结果是
1
。
问题转化:
实际上,这道题可以转化为图论中的 连通分量 问题:
- 矩阵中的每个服务器可以看作是图中的一个节点;
- 如果两个服务器之间存在直接连接(即
matrix[i][j] == 1
),则它们之间存在一条边; - 题目要求的是图中的连通分量的个数。每个连通分量中只需要选择一个服务器发起广播即可,所以连通分量的数量就是答案。
Java
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 首先读取第一行,并将其通过空格拆分成字符串数组
String[] str = in.nextLine().split(" ");
int n = str.length; // 服务器的数量,n 为矩阵的维度
// 创建 n*n 的二维数组来存储服务器连接状态
int[][] arr = new int[n][n];
// 将第一行的连接状态转换为整数并存入数组 arr
for(int i = 0; i < n; i++) {
arr[0][i] = Integer.parseInt(str[i]);
}
// 读取剩下的 n-1 行,并逐行存入 arr 矩阵
for(int i = 1; i < n; i++) {
String[] s = in.nextLine().split(" ");
for(int j = 0; j < n; j++) {
arr[i][j] = Integer.parseInt(s[j]);
}
}
int count = 0; // 计数器,记录连通分量的数量(即需要广播的服务器数量)
// 使用队列来记录访问过的节点(服务器)
Queue<Integer> queue = new LinkedList<>();
// 遍历每个服务器,如果该服务器没有被访问过,就执行 DFS,找到其所有连通的服务器
for(int i = 0; i < n; i++) {
if(!queue.contains(i)) {
// 如果该服务器不在已访问队列中
dfs(arr, queue, i); // 执行深度优先搜索
count++; // 每次找到一个新的连通分量,计数器加1
}
}
// 输出需要广播的服务器数量
System.out.println(count);
}
// 深度优先搜索函数,递归查找服务器的所有连通节点
public static void dfs(int[][] arr, Queue<Integer> queue, int index) {
queue.offer(index); // 将当前服务器加入已访问队列
// 从当前服务器开始,查找所有直接相连的服务器