华为OD机试真题 Java 实现【城市聚集度】【2023 B卷 200分】,附详细解题思路

在这里插入图片描述

目录

    • 专栏导读
    • 一、题目描述
    • 二、输入描述
    • 三、输出描述
    • 四、解题思路
    • 五、Java算法源码
    • 六、效果展示
      • 1、输入
      • 2、输出
      • 3、说明

华为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

三、输出描述

输出城市的编号,如果有多个,按照编号升序输出。

四、解题思路

  1. 输入一张地图上有N个城市;
  2. 输入n-1条关系;
  3. 定义最小的最大连通块大小min;
  4. 定义最小的最大连通块所在的城市cityList;
  5. 遍历每个城市作为特殊城市;
    • 初始化并查集;
    • 将与特殊城市相连的边删除;
    • 定义map,key:连通块,value:连通块大小;
    • 定义最大连通块大小max;
    • 如果当前最大连通块大小比之前的最小值还小,则更新最小值和最小值所在的城市;
    • 如果当前最大连通块大小与之前的最小值相等,则将城市加入最小值所在的城市列表;
  6. 输出最小的最大连通块所在的城市。

五、Java算法源码

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 + " ");
        }
    }
}

六、效果展示

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。

华为OD机试真题 Java 实现【城市聚集度】【2023 B卷 200分】,附详细解题思路_第1张图片


下一篇:华为OD机试真题 Java 实现【路灯照明问题】【2022Q4 100分】,感谢fly晨发现这个问题,并提供更优质的算法

本文收录于,华为OD机试(JAVA)真题(A卷+B卷)

刷的越多,抽中的概率越大,每一题都有详细的答题思路、详细的代码注释、样例测试,发现新题目,随时更新,全天CSDN在线答疑。

在这里插入图片描述

你可能感兴趣的:(搬砖工逆袭Java架构师,华为od,java,python,学习,程序人生,华为)