华为OD机试 2025A卷题库疯狂收录中,刷题点这里
专栏导读
本专栏收录于《华为OD机试真题(Python/JS/C/C++)》。
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。
一、题目描述
一张地图上有N个城市,城市和城市之间有且只有一条道路相连,要么直接相连,要么通过其他城市中转相连(可中转一次或多次)。城市与城市之间的道路都不会成环。
当切断通往某城市i的所有道路后,地图上将分成多个连通的城市群,设该城市i的聚集度为DPi of Polymerization), DPi = max(城市群1的城市个数,城市群2的城市个数,…城市群m的城市个数)。 请找出地图上DP值最小的城市(即找到城市j,使得DPj = min(DP1,DP2…DPn))。
提示:如果有多个城市都满足条件,这些城市都要找出来(可能存在多个解)。
提示:DPi的计算,可以理解为已知一个树,删除某个节点后,生成的多个字树,求解多个字树节点数的问题。
二、输入描述
每个样例,第一行有一个整数N,表示有N个节点,1 <=N <=1000
j接下来的N-1行每行有两个整数x,y,表示城市x与城市y连接。1 <= x , y <= N
三、输出描述
输出城市的编号,如果有多个,按照编号升序输出。
四、测试用例
四、测试用例
测试用例1:
1、输入
5
1 2
2 3
3 4
4 5
2、输出
3
3、说明
对于城市3,切断通往3的所有道路后,形成2个城市群[(1,2),(4,5)],其聚集度分别都是2,。DP3 = 2。
对于城市4,切断通往城市4的所有道路后,形成2个城市群[(1,2,3),(5)],DP4 = max(3,1) = 3。
以此类推,切断其他城市的所有道路后,得到的DP都会大于2,因为城市3就是满足条件的城市,输出是3。
测试用例2:
1、输入
4
1 2
2 3
2 4
2、输出
2
3、说明
删除城市2会导致两个子图:{1} 和 {3, 4},最大连通块的大小是2,聚集度最小。
测试用例3:
1、输入
5
1 2
1 3
2 4
2 5
2、输出
2
3、说明
删除城市2后,会生成两个子图,{1} 和 {3, 4, 5}。其中,最大连通块的大小为3,聚集度最小。
五、解题思路
- 输入一张地图上有N个城市;
- 输入n-1条关系;
- 定义最小的最大连通块大小min;
- 定义最小的最大连通块所在的城市cityList;
- 遍历每个城市作为特殊城市;
- 初始化并查集;
- 将与特殊城市相连的边删除;
- 定义map,key:连通块,value:连通块大小;
- 定义最大连通块大小max;
- 如果当前最大连通块大小比之前的最小值还小,则更新最小值和最小值所在的城市;
- 如果当前最大连通块大小与之前的最小值相等,则将城市加入最小值所在的城市列表;
- 输出最小的最大连通块所在的城市。
六、Python算法源码
class FindUnionSet:
def __init__(self, n):
self.fatherArr = list(range(n))
def find(self, x):
if self.fatherArr[x] != x:
self.fatherArr[x] = self.find(self.fatherArr[x]) # Path compression
return self.fatherArr[x]
def unionSet(self, x, y):
x_father = self.find(x)
y_father = self.find(y)
if x_father != y_father:
self.fatherArr[y_father] = x_father
def main():
n = int(input())
relationArrs = [tuple(map(int, input().split())) for _ in range(n - 1)]
min_value = float('inf')
cityList = []
for i in range(1, n + 1):
fus = FindUnionSet(n + 1)
for x, y in relationArrs:
if x != i and y != i:
fus.unionSet(x, y)
city_map = {}
for j in range(1, n + 1):
root = fus.find(j)
city_map[root] = city_map.get(root, 0) + 1
max_value = max(city_map.values())
if max_value < min_value:
min_value = max_value
cityList = [i]
elif max_value == min_value:
cityList.append(i)
print(" ".join(map(str, cityList)))
if __name__ == "__main__":
main()
七、JavaScript算法源码
class FindUnionSet {
constructor(n) {
this.fatherArr = Array.from({ length: n }, (_, index) => index);
}
find(x) {
if (this.fatherArr[x] !== x) {
this.fatherArr[x] = this.find(this.fatherArr[x]); // Path compression
}
return this.fatherArr[x];
}
unionSet(x, y) {
let x_father = this.find(x);
let y_father = this.find(y);
if (x_father !== y_father) {
this.fatherArr[y_father] = x_father;
}
}
}
function main() {
let n = parseInt(prompt());
let relationArrs = [];
for (let i = 0; i < n - 1; i++) {
let [x, y] = prompt().split(' ').map(Number);
relationArrs.push([x, y]);
}
let min = Number.MAX_SAFE_INTEGER;
let cityList = [];
for (let i = 1; i <= n; i++) {
let fus = new FindUnionSet(n + 1);
for (let [x, y] of relationArrs) {
if (x !== i && y !== i) {
fus.unionSet(x, y);
}
}
let cityMap = {};
for (let j = 1; j <= n; j++) {
let root = fus.find(j);
cityMap[root] = (cityMap[root] || 0) + 1;
}
let max = Math.max(...Object.values(cityMap));
if (max < min) {
min = max;
cityList = [i];
} else if (max === min) {
cityList.push(i);
}
}
console.log(cityList.join(' '));
}
main();
八、C算法源码
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
typedef struct {
int *fatherArr;
} FindUnionSet;
FindUnionSet* createFindUnionSet(int n) {
FindUnionSet *fus = (FindUnionSet*)malloc(sizeof(FindUnionSet));
fus->fatherArr = (int*)malloc(sizeof(int) * n);
for (int i = 0; i < n; i++) {
fus->fatherArr[i] = i;
}
return fus;
}
int find(FindUnionSet *fus, int x) {
if (fus->fatherArr[x] != x) {
fus->fatherArr[x] = find(fus, fus->fatherArr[x]); // Path compression
}
return fus->fatherArr[x];
}
void unionSet(FindUnionSet *fus, int x, int y) {
int x_father = find(fus, x);
int y_father = find(fus, y);
if (x_father != y_father) {
fus->fatherArr[y_father] = x_father;
}
}
int main() {
int n;
scanf("%d", &n);
int relationArrs[n - 1][2];
for (int i = 0; i < n - 1; i++) {
scanf("%d %d", &relationArrs[i][0], &relationArrs[i][1]);
}
int min = INT_MAX;
int cityList[n];
int cityCount = 0;
for (int i = 1; i <= n; i++) {
FindUnionSet *fus = createFindUnionSet(n + 1);
for (int j = 0; j < n - 1; j++) {
int x = relationArrs[j][0];
int y = relationArrs[j][1];
if (x != i && y != i) {
unionSet(fus, x, y);
}
}
int max = 0;
int cityMap[n + 1];
for (int j = 0; j < n + 1; j++) cityMap[j] = 0;
for (int j = 1; j <= n; j++) {
int root = find(fus, j);
cityMap[root]++;
}
for (int j = 1; j <= n; j++) {
if (cityMap[j] > max) max = cityMap[j];
}
if (max < min) {
min = max;
cityCount = 0;
cityList[cityCount++] = i;
} else if (max == min) {
cityList[cityCount++] = i;
}
}
for (int i = 0; i < cityCount; i++) {
printf("%d ", cityList[i]);
}
return 0;
}
九、C++算法源码
#include <iostream>
#include <vector>
#include <climits>
#include <map>
#include <algorithm>
class FindUnionSet {
public:
std::vector<int> fatherArr;
FindUnionSet(int n) {
fatherArr.resize(n);
for (int i = 0; i < n; i++) {
fatherArr[i] = i;
}
}
int find(int x) {
if (fatherArr[x] != x) {
fatherArr[x] = find(fatherArr[x]); // Path compression
}
return fatherArr[x];
}
void unionSet(int x, int y) {
int x_father = find(x);
int y_father = find(y);
if (x_father != y_father) {
fatherArr[y_father] = x_father;
}
}
};
int main() {
int n;
std::cin >> n;
std::vector<std::pair<int, int>> relationArrs(n - 1);
for (int i = 0; i < n - 1; i++) {
std::cin >> relationArrs[i].first >> relationArrs[i].second;
}
int min = INT_MAX;
std::vector<int> cityList;
for (int i = 1; i <= n; i++) {
FindUnionSet fus(n + 1);
for (auto &[x, y] : relationArrs) {
if (x != i && y != i) {
fus.unionSet(x, y);
}
}
std::map<int, int> cityMap;
for (int j = 1; j <= n; j++) {
int root = fus.find(j);
cityMap[root]++;
}
int max = 0;
for (auto &[root, count] : cityMap) {
max = std::max(max, count);
}
if (max < min) {
min = max;
cityList = {i};
} else if (max == min) {
cityList.push_back(i);
}
}
for (int city : cityList) {
std::cout << city << " ";
}
return 0;
}
🏆下一篇:华为OD机试真题 - 简易内存池(Python/JS/C/C++ 2025 A卷 200分)
🏆本文收录于,华为OD机试真题(Python/JS/C/C++)
刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。