华为机考真题 -- 找城市

题目描述:

一张地图上有n个城市,城市和城市之间有且只有一条道路相连:要么直接相连,要么通过其它城市中转相连(可中转一次或多次),城市与城市之间的道路都不会成环。

当切断通往某个城市 i 的所有道路后,地图上将分为多个连通的城市群,设该城市i的聚集度为DPi,DPi = max(城市群1的城市个数,城市群2的城市个数,…城市群m 的城市个数);

请找出地图上DP值最小的城市(即找到城市j,使得DPj = min(DP1,DP2 … DPn))

提示:
1. 如果有多个城市都满足条件,这些城市都要找出来(可能存在多个解)
2. DPi的计算,可以理解为已知一棵树,删除某个节点后;生成的多个子树,求解多个子数节点数的问题。

输入描述:

第一行有一个整数N,表示有N个节点,1 <= N <= 1000;
接下来的N-1行每行有两个整数x,y,表示城市x与城市y连接, 
1 <= x,  y <= N;

输出描述:

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

示例1:

输入
5
1 2
2 3
3 4
4 5

输出
3

说明:输入表示的是如下地图:1 - 2 -3 - 4 - 5
对于城市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就是DP值最小的城市,输出3;

示例2:

输入
6
1 2
2 3
2 5
3 4
3 6

输出
2 3

说明:输入表示的是如下地图:
       6 
       |
1 - 2 -3 - 4
    |
    5
对于城市2,切断通往2的所有道路后,形成3个城市群[(1),(5),(3,4,6)],其聚集度分别都是1,1,3,DP2=max(1,1,3)=3。
对于城市3,切断通往3的所有道路后,形成3个城市群[(1,2,5),(4),(6)],其聚集度DP3=max(3,1.1)=3。
依次类推,切断其他城市所有道理后,得到的DP都会大于3,因此城市2、3就是DP值最小的城市,升序排列输出是2 3;

C++源码:

#include <iostream>
#include <vector>
#include <unordered_map>
#include <algorithm>
using namespace std;

// 使用邻接表来存储每个城市与其相连的城市
unordered_map<int, vector<int>> linkCity;
vector<int> dp;

// 深度优先搜索,用于计算从城市u出发,不通过城市cutCity所能到达的城市数
int dfs(int u, int cutCity) {
	int cityNum = 1; // 初始化当前城市计数为1
	for (int v : linkCity[u]) {
		if (v == cutCity) {
			continue; // 避免回到上一个城市,即父节点
		}
		cityNum += dfs(v, u); // 递归计算子城市的总数,并累加
	}
	return cityNum; // 返回从当前城市出发的总城市数
}

void dpFind(const vector<pair<int, int>>& connections) {
	int n = connections.size() + 1;
	// 构建城市之间的连接关系
	for (const auto& conn : connections) {
		int u = conn.first;
		int v = conn.second;
		linkCity[u].push_back(v);
		linkCity[v].push_back(u);
	}

	dp.resize(n + 1, 0); // 创建一个数组用来存储每个城市的聚集度

	// 计算每个城市的聚集度
	for (int i = 1; i <= n; ++i) {
		for (int x : linkCity[i]) {
			dp[i] = max(dp[i], dfs(x, i)); // 使用dfs函数来找出以该城市为根节点,断开后的最大连通城市数
		}
	}
	// 找到最小的聚集度
	int minval = *min_element(dp.begin() + 1, dp.end());
	// 输出所有具有最小聚集度的城市编号
	for (int i = 1; i <= n; ++i) {
		if (dp[i] == minval) {
			cout << i << " ";
		}
	}
	cout << endl;
}

int main() {
	int n;
	cin >> n; // 读取城市数量
	vector<pair<int, int>> connections(n - 1); // 存储城市间连接关系
	// 读取城市之间的连接关系
	for (auto& conn : connections) {
		cin >> conn.first >> conn.second;
	}

	dpFind(connections);
	system("pause");
	return 0;
}

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
华为OD机考真题是指华为公司在招聘过程中所使用的在线机考试题目。这些题目旨在评估应聘者的技术能力、逻辑思维以及解决问题的能力。以下是对华为OD机考真题解读的简要说明。 华为OD机考真题的内容丰富多样,主要涵盖计算机科学、网络技术、算法设计、数据结构等多个领域。对于应聘者来说,这些题目不仅要求具备扎实的专业知识,还要求能够将知识应用于实际场景中,并能够灵活运用、创新思考。 在解答华为OD机考真题时,应聘者需要具备良好的解题思路和方法。首先,应聘者需要仔细阅读题目,理解题意和要求,明确问题的关键点。其次,应聘者需要运用所学知识和技能分析问题,并制定解决方案。此时,良好的逻辑思维和分析能力是十分重要的。最后,应聘者需要将解决方案转化为具体的代码实现或解题步骤,并进行测试和验证。 华为OD机考真题的目的是为了筛选出具备优秀技术能力和解决问题能力的人才。在解题过程中,华为注重考察应聘者的创新能力和解决问题的能力,不仅关注结果,还关注解决问题的思路和方法。因此,应聘者在回答真题时除了要给出正确的答案,还需要展现出对问题的全面思考和独立思考的能力。 总之,华为OD机考真题的解答需要应聘者具备扎实的专业知识、良好的解题思路、逻辑思维能力和解决问题的能力。这些真题旨在筛选出具备创新思维和解决问题能力的优秀人才。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值