华为OD机试 - 城市聚集度(Python/JS/C/C++ 2025 A卷 200分)

在这里插入图片描述

华为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,聚集度最小。

五、解题思路

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

六、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算法的适用场景,发现新题目,随时更新。

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

哪 吒

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值