华为OD机试 2023B卷题库疯狂收录中,刷题点这里
本专栏收录于《华为OD机试(JAVA)真题(A卷+B卷)》。
刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试,发现新题目,随时更新,全天CSDN在线答疑。
一张地图上有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
输出城市的编号,如果有多个,按照编号升序输出。
package com.guor.od;
import java.util.*;
public class OdTest {
static class FindUnionSet {
// 存储每个节点的父节点
private int[] fatherArr;
// 初始化并查集,每个节点的父节点为自己
public FindUnionSet(int n) {
fatherArr = new int[n];
for (int i = 0; i < n; i++) fatherArr[i] = i;
}
// 查找x的祖先节点,路径压缩优化
public int find(int x) {
if (fatherArr[x] != x) {
fatherArr[x] = find(fatherArr[x]);
}
return fatherArr[x];
}
// 合并x和y所在的集合
public void unionSet(int x, int y) {
int x_father = find(x);
int y_father = find(y);
// 如果x和y不在同一个集合中,则将y的祖先节点设为x的祖先节点
if (x_father != y_father) {
fatherArr[y_father] = x_father;
}
}
}
public static void main(String[] args) throws Exception {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
// 存储n-1条关系
int[][] relationArrs = new int[n - 1][2];
// 输入n-1条关系
for (int i = 0; i < n - 1; i++) {
relationArrs[i][0] = sc.nextInt();
relationArrs[i][1] = sc.nextInt();
}
// 最小的最大连通块大小
int min = Integer.MAX_VALUE;
// 最小的最大连通块所在的城市
List<Integer> cityList = new ArrayList<>();
// 枚举每个城市作为特殊城市
for (int i = 1; i <= n; i++) {
// 初始化并查集
FindUnionSet fus = new FindUnionSet(n + 1);
// 将与特殊城市相连的边删除
for (int[] relationArr : relationArrs) {
int x = relationArr[0];
int y = relationArr[1];
if (x == i || y == i) {
continue;
}
fus.unionSet(x, y);
}
// key:连通块
// value:连通块大小
Map<Integer, Integer> map = new HashMap<>();
for (int father : fus.fatherArr) {
father = fus.find(father);
map.put(father, map.getOrDefault(father, 0) + 1);
}
// 最大连通块大小
int max = 0;
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
max = Math.max(max, entry.getValue());
}
// 如果当前最大连通块大小比之前的最小值还小,则更新最小值和最小值所在的城市
if (max < min) {
min = max;
cityList.clear();
cityList.add(i);
// 如果当前最大连通块大小与之前的最小值相等,则将城市加入最小值所在的城市列表
} else if (max == min) {
cityList.add(i);
}
}
// 输出最小的最大连通块所在的城市
for (int city : cityList) {
System.out.print(city + " ");
}
}
}
5
1 2
2 3
3 4
4 5
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。
下一篇:华为OD机试真题 Java 实现【路灯照明问题】【2022Q4 100分】,感谢fly晨发现这个问题,并提供更优质的算法
本文收录于,华为OD机试(JAVA)真题(A卷+B卷)
刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试,发现新题目,随时更新,全天CSDN在线答疑。