牛客题解 | 寻宝

news/2025/3/4 12:26:56/文章来源:https://www.cnblogs.com/wc529065/p/18750290

题目

题目链接

解题思路

这是一个最小生成树问题,需要找到连接所有空地的最小生成树,并且要求最长的边最小。这种问题可以使用Kruskal算法的变体来解决。

关键点:

  1. 使用Kruskal算法构建最小生成树
  2. 按照边的长度排序
  3. 使用并查集维护连通性
  4. 找到满足条件的最小最大边

算法步骤:

  1. 对所有边按长度排序
  2. 使用二分查找最小的最大边长度
  3. 检查是否能连通所有点
  4. 返回满足条件的最小值

代码

#include <bits/stdc++.h>
using namespace std;class UnionFind {
private:vector<int> parent;vector<int> rank;int count;public:UnionFind(int n) : parent(n), rank(n, 0), count(n) {for (int i = 0; i < n; i++) {parent[i] = i;}}int find(int x) {if (parent[x] != x) {parent[x] = find(parent[x]);}return parent[x];}void unite(int x, int y) {int rootX = find(x);int rootY = find(y);if (rootX != rootY) {if (rank[rootX] < rank[rootY]) {swap(rootX, rootY);}parent[rootY] = rootX;if (rank[rootX] == rank[rootY]) {rank[rootX]++;}count--;}}bool isConnected(int x, int y) {return find(x) == find(y);}int getCount() {return count;}
};class Solution {
public:int findMinMaxEdge(int n, vector<vector<int>>& edges) {// 按边长排序sort(edges.begin(), edges.end(), [](const vector<int>& a, const vector<int>& b) {return a[2] < b[2];});int left = 0, right = edges.back()[2];int result = right;while (left <= right) {int mid = left + (right - left) / 2;// 检查是否能用不超过mid长度的边连通所有点if (canConnect(n, edges, mid)) {result = mid;right = mid - 1;} else {left = mid + 1;}}return result;}private:bool canConnect(int n, const vector<vector<int>>& edges, int maxLen) {UnionFind uf(n + 1);// 只使用长度不超过maxLen的边for (const auto& edge : edges) {if (edge[2] > maxLen) break;uf.unite(edge[0], edge[1]);}// 检查是否所有点都连通(除了0)int root = uf.find(1);for (int i = 2; i <= n; i++) {if (uf.find(i) != root) return false;}return true;}
};int main() {ios::sync_with_stdio(false);cin.tie(nullptr);int n, m;cin >> n >> m;vector<vector<int>> edges(m, vector<int>(3));for (int i = 0; i < m; i++) {cin >> edges[i][0] >> edges[i][1] >> edges[i][2];}Solution solution;cout << solution.findMinMaxEdge(n, edges) << endl;return 0;
}
import java.util.*;class UnionFind {private int[] parent;private int[] rank;private int count;public UnionFind(int n) {parent = new int[n];rank = new int[n];count = n;for (int i = 0; i < n; i++) {parent[i] = i;}}public int find(int x) {if (parent[x] != x) {parent[x] = find(parent[x]);}return parent[x];}public void unite(int x, int y) {int rootX = find(x);int rootY = find(y);if (rootX != rootY) {if (rank[rootX] < rank[rootY]) {int temp = rootX;rootX = rootY;rootY = temp;}parent[rootY] = rootX;if (rank[rootX] == rank[rootY]) {rank[rootX]++;}count--;}}public boolean isConnected(int x, int y) {return find(x) == find(y);}public int getCount() {return count;}
}class Solution {private boolean canConnect(int n, int[][] edges, int maxLen) {UnionFind uf = new UnionFind(n + 1);// 只使用长度不超过maxLen的边for (int[] edge : edges) {if (edge[2] > maxLen) break;uf.unite(edge[0], edge[1]);}// 检查是否所有点都连通int root = uf.find(1);for (int i = 2; i <= n; i++) {if (uf.find(i) != root) return false;}return true;}public int findMinMaxEdge(int n, int[][] edges) {// 按边长排序Arrays.sort(edges, (a, b) -> Integer.compare(a[2], b[2]));int left = 0, right = edges[edges.length - 1][2];int result = right;while (left <= right) {int mid = left + (right - left) / 2;if (canConnect(n, edges, mid)) {result = mid;right = mid - 1;} else {left = mid + 1;}}return result;}
}public class Main {public static void main(String[] args) {Scanner sc = new Scanner(System.in);int n = sc.nextInt();int m = sc.nextInt();int[][] edges = new int[m][3];for (int i = 0; i < m; i++) {edges[i][0] = sc.nextInt();edges[i][1] = sc.nextInt();edges[i][2] = sc.nextInt();}Solution solution = new Solution();System.out.println(solution.findMinMaxEdge(n, edges));sc.close();}
}
class UnionFind:def __init__(self, n):self.parent = list(range(n))self.rank = [0] * nself.count = ndef find(self, x):if self.parent[x] != x:self.parent[x] = self.find(self.parent[x])return self.parent[x]def unite(self, x, y):root_x = self.find(x)root_y = self.find(y)if root_x != root_y:if self.rank[root_x] < self.rank[root_y]:root_x, root_y = root_y, root_xself.parent[root_y] = root_xif self.rank[root_x] == self.rank[root_y]:self.rank[root_x] += 1self.count -= 1def is_connected(self, x, y):return self.find(x) == self.find(y)def get_count(self):return self.countclass Solution:def can_connect(self, n: int, edges: list, max_len: int) -> bool:uf = UnionFind(n + 1)# 只使用长度不超过max_len的边for edge in edges:if edge[2] > max_len:breakuf.unite(edge[0], edge[1])# 检查是否所有点都连通root = uf.find(1)return all(uf.find(i) == root for i in range(2, n + 1))def find_min_max_edge(self, n: int, edges: list) -> int:# 按边长排序edges.sort(key=lambda x: x[2])left, right = 0, edges[-1][2]result = rightwhile left <= right:mid = left + (right - left) // 2if self.can_connect(n, edges, mid):result = midright = mid - 1else:left = mid + 1return resultdef main():n, m = map(int, input().split())edges = []for _ in range(m):p, q, k = map(int, input().split())edges.append([p, q, k])solution = Solution()print(solution.find_min_max_edge(n, edges))if __name__ == "__main__":main()

算法及复杂度

  • 算法:Kruskal算法 + 二分查找
  • 时间复杂度:\(\mathcal{O(M \log M + M \log K)}\),其中 \(M\) 是边数,\(K\) 是最大边长
  • 空间复杂度:\(\mathcal{O(N)}\),用于并查集数据结构

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/893370.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

什么是项目管理?五大流程是什么?

项目管理这东西,大家可能听过,但是具体怎么操作,很多人可能就一头雾水了。 简单来说,项目管理就是为了完成某个特定目标,把时间、资源、人员等因素有条不紊地组织、协调、控制和调整,最终确保项目按时、按预算、高质量地完成。 这个“项目”可以是任何东西,比如公司新产…

最全面的浏览器教程-完结撒花

完结撒花 🎉🎉🎉完结撒花 🎉🎉🎉 《最全面的浏览器教程》目前要告一段落了,耗时我一个多月,整理了大量的笔记,参考了很多教程和文章,累计写了 24 篇文章,7.3 万字,200 多张图片,收获了很多粉丝和鼓励,在此表示感谢。 如果后续有学到什么新技巧,看到好玩意…

牛客题解 | 字符串相乘

牛客题库题解题目 题目链接 题解 题目难度:中等难度 知识点:字符串、大数相乘 模拟人工计算 计算的过程基本上和小学生列竖式做乘法相同。为编程方便,并不急于处理进位,而将进位问题留待最后统一处理。数组a存储第一个数字123(逆序)数组b存储第二数组20(逆序)结果存入数…

皮尔逊、斯皮尔曼、肯德尔相关系数

相关系数和特征选择 相关系数和特征选择,一个是属性,一个是特征。一般,把数据集中的各列成为属性,而对算法模型表现有益的属性成为特征。例如,在预测泰坦尼克乘客的存活情况时,乘客姓名这个属性对我们的预测可能没有帮助,甚至会干扰模型表现;而乘客年龄、性别或许与存活…

认识 TapFlow,以编程方式运行 TapData

TapFlow 是 TapData Live Data Platform 最新推出的一个面向编程的API 框架。TapFlow 可以让开发者和数据工程师用一个简单易用而又强大的编程语言来进行数据管道和数据模型的开发工作。**什么是TapFlow? ** TapFlow 是 TapData Live Data Platform 最新推出的一个面向编程的A…

Maya 影视渲染,渲染101 让创作无压力!

Maya 创作时,渲染是不是常让人崩溃?漫长等待、电脑性能不足、报错频出,今天就给大家分享基于渲染 101 平台的 Maya 云渲染,轻松解决这些难题!告别漫长等待,效率飙升**** 自己电脑渲染复杂 Maya 项目,耗时久,进度慢。渲染 101 的云渲染有强大计算集群,众多高性能服务器…

Java SpringBoot 升级后,编译打包都没问题,运行报错

编译打包都没问题,运行报错 10:36:39,587 |-INFO in ch.qos.logback.classic.joran.JoranConfigurator@5966cc - Registering current configuration as safe fallback point Exception in thread "main" java.lang.NoClassDefFoundError: org/springframework/core…

在Hyper-V虚拟化平台上,怎么创建和管理虚拟机呢?

确实,在Hyper-V虚拟化平台上,创建和管理虚拟机(VMs)是实现资源高效利用和业务灵活部署的关键。以下是对这一观点的详细阐述:一、创建虚拟机:资源高效利用的基础 资源分配与优化: 在创建虚拟机时,管理员需要根据业务需求合理分配CPU、内存、存储和网络等资源。通过精确的…

STM32实战——ESP8266 WIFI模块

此篇博文提供了ESP8266的开发指南,包括在STM32上使用ESP8266进行WiFi连接、发送和接收HTTP请求以及在ESP8266中使用AT指令发送GET方式请求等内容。ESP8266 硬件介绍 ESP8266系列模组有哪些:在本实验中,ESP8266与ESP-01不做区分。 ESP-01引脚介绍:引脚 功能3.3 3.3V供电,避…

一招学会Prometheus对接三方监控平台

文章来源:乐维社区 通过将Prometheus与不同的监控工具和服务集成,企业可以实现对更广泛资源和服务的监控,包括那些不由Prometheus原生支持的系统。这种集成不仅有助于获取更全面、深入的监控数据,还能提升故障排查和性能优化的效率,从而确保系统的稳定性和可靠性。 环境说…

Motoman机器人XRC控制柜维修

在现代工业生产中,YASKAWA机器人扮演着至关重要的角色。然而,如同所有的机械设备一样,YASKAWA机器人也会出现故障,尤其是其控制柜部分。因此,安川机器人维修工作对于保障机器人的正常运行意义非凡,这其中安川机器人控制柜维修更是关键环节。一、常见故障及解决方法1. 电源…

【域攻击】无文件落地攻击:msiexec

msiexec.exe属于系统进程,是Windows Installer的一部分,用于安装Windows Installer安装包(MSI),对系统的正常运行非常重要,一般在运行Microsoft Update安装更新或安装部分软件的时候出现,占用内存比较大,我们亦可以使用其作为无文件落地的媒介,下面举例说明: Step 1:使…