《算法竞赛·快冲300题》每日一题:“最小生成树”
《算法竞赛·快冲300题》将于2024年出版,是《算法竞赛》的辅助练习册。
所有题目放在自建的OJ New Online Judge。
用C/C++、Java、Python三种语言给出代码,以中低档题为主,适合入门、进阶。
文章目录
- 题目描述
- 题解
- C++代码
- Java代码
- Python代码
“ 最小生成树” ,链接: http://oj.ecustacm.cn/problem.php?id=1804
题目描述
【题目描述】
在平面中有n个点(xi,yi),两点之间的距离为欧几里得距离的平方。
求最小生成树的权重。
平面坐标满足:(0≤xi≤1000000,0≤yi≤10)
【输入格式】 输入第一行为正整数n,n不超过100000。
接下来n行,每行两个整数x和y,表示坐标点(x,y)。
【输出格式】 输出一个数表示答案。
【输入样例】
10
83 10
77 2
93 4
86 6
49 1
62 7
90 3
63 4
40 10
72 0
【输出样例】
660
题解
本题差不多是一道最小生成树的模板题,但是需要处理好边。本题的任意两点间有边,边的总数量约为 n 2 / 2 n^2/2 n2/2,而n最大是 1 0 6 10^6 106, n 2 / 2 n^2/2 n2/2条边显然会超出空间限制。
能否减少边的数量?注意到本题所有点的y坐标的限制是0≤yi≤10,这n个点的y坐标都在0和10之间。在平面上画11根横线;y=0,y=1,…,y=11,那么n个点都会在这11根线上。当处理到第i点时,只要把它和左边的11根线上的最近点连接,并且把它与右边的11根线上的最近点连接即可。这样得到的边,仍然会连通所有点,并且保留了最短的边。这样,每个点只需要连22个边,总边数只有22×n条。
不过还可以简化,对每个点,只连它左边的11条边即可,不用连右边的边,请思考为什么。
处理好边后,其他代码就是标准的最小生成树的模板。本题的边数不多,用代码比较简单的Kruskal算法编码。
【笔记】 最小生成树。
C++代码
#include<bits/stdc++.h>
using namespace std;
#define Mul(a) ((long long)(a) * (a))
const int N = 1e5 + 10;
typedef pair<int, int> Node;
int n, m; //点、边
Node a[N]; //n个点的坐标
struct edge{int u, v;long long w;
}e[N * 22]; //边的数量。如果只连左边的11条边,这里改为N*11
bool cmp(edge a, edge b){ return a.w < b.w;} //从小到大排序
void add_edge(int u, int v) { //点u和点v连边m++;e[m].u = u;e[m].v = v;e[m].w = Mul(a[u].first - a[v].first) + Mul(a[u].second - a[v].second);
}
int s[N];//并查集
int find_set(int x){ //查询并查集,返回x的根if(x != s[x])s[x] = find_set(s[x]); //路径压缩return s[x];
}
void kruskal(){for(int i = 1; i <= n; i++) s[i] = i; //并查集初始化sort(e + 1, e + 1 + m,cmp); //边排序long long ans = 0;for(int i = 1; i <= m; i++){ //从小到大遍历边,加入到最小生成树int u = find_set(e[i].u), v = find_set(e[i].v);if(u==v) continue; //产生了圈,丢弃else s[u] = v, ans += e[i].w;}cout<<ans<<endl;
}
int Last[15];
int main(){cin >> n;for(int i = 1; i <= n; i++) cin >> a[i].first >> a[i].second;sort(a + 1, a + 1 + n); //对点排序。实际是对x从小到大排序//每个点往每行的左边最近点连边for(int i = 0; i <= 10; i++) Last[i] = 0;for(int i = 1; i <= n; i++) {for(int y = 0; y <= 10; y++)if(Last[y]) add_edge(i, Last[y]);Last[a[i].second] = i;}//每个点往每行的右边最近点连边。可以省略/* for(int i = 0; i <= 10; i++)Last[i] = 0;for(int i = n; i >= 1; i--) {for(int y = 0; y <= 10; y++)if(Last[y]) add_edge(i, Last[y]);Last[a[i].second] = i;}*/kruskal();return 0;
}
Java代码
import java.util.*;public class Main {static class Node implements Comparable<Node>{int x, y;Node(int x, int y) {this.x = x;this.y = y;}public int compareTo(Node o) {return Integer.compare(this.x, o.x);}}static class Edge implements Comparable<Edge>{int u, v;long w;Edge(int u, int v, long w) {this.u = u;this.v = v;this.w = w;}public int compareTo(Edge o) {return Long.compare(this.w, o.w);}}static final int N = 1_00_005;static Node[] a = new Node[N];static Edge[] e = new Edge[N * 11];static int[] s = new int[N];static int[] Last = new int[15];static int n, m;static long mul(int a) { return (long)a * a; }static void addEdge(int u, int v) {m++;e[m] = new Edge(u, v, mul(a[u].x - a[v].x) + mul(a[u].y - a[v].y));}static int findSet(int x) {if (x != s[x])s[x] = findSet(s[x]);return s[x];}static void kruskal() {for (int i = 1; i <= n; i++) s[i] = i;Arrays.sort(e, 1, m + 1);long ans = 0;for (int i = 1; i <= m; i++) {int u = findSet(e[i].u), v = findSet(e[i].v);if (u == v) continue;s[u] = v;ans += e[i].w;}System.out.println(ans);}public static void main(String[] args) {Scanner sc = new Scanner(System.in);n = sc.nextInt();for (int i = 1; i <= n; i++) {int x = sc.nextInt(), y = sc.nextInt();a[i] = new Node(x, y);}Arrays.sort(a, 1, n + 1);for (int i = 0; i <= 10; i++) Last[i] = 0;for (int i = 1; i <= n; i++) {for (int y = 0; y <= 10; y++) if (Last[y] > 0) addEdge(i, Last[y]);Last[a[i].y] = i;}kruskal();}
}
Python代码
from typing import List, Tuple
def mul(b): return b * b
class Node:def __init__(self, x: int, y: int):self.x = xself.y = ydef __lt__(self, other: "Node") -> bool:return self.x < other.x
class Edge:def __init__(self, u: int, v: int, w: int):self.u = uself.v = vself.w = wdef __lt__(self, other: "Edge") -> bool:return self.w < other.w
N = 100005
a: List[Node] = [Node(0, 0) for i in range(N)]
e: List[Edge] = [Edge(0, 0, 0) for i in range(N * 11)]
s: List[int] = [i for i in range(N)]
Last: List[int] = [0] * 15
n = m = 0
def addEdge(u: int, v: int) -> None:global mm += 1e[m].u = ue[m].v = ve[m].w = mul(a[u].x - a[v].x) + mul(a[u].y - a[v].y)def findSet(x: int) -> int:global sif x != s[x]: s[x] = findSet(s[x])return s[x]def kruskal() -> None:global n, m, s, efor i in range(1, n + 1): s[i] = ie[1:] = sorted(e[1:m + 1])ans = 0for i in range(1, m + 1):u = findSet(e[i].u)v = findSet(e[i].v)if u == v: continues[u] = vans += e[i].wprint(ans)
if __name__ == "__main__":n = int(input())for i in range(1, n + 1):x, y = map(int, input().split())a[i] = Node(x, y)a[1:] = sorted(a[1:n + 1])Last = [0] * 15for i in range(1, n + 1):for y in range(11):if Last[y] > 0: addEdge(i, Last[y])Last[a[i].y] = ikruskal()
相关文章:
《算法竞赛·快冲300题》每日一题:“最小生成树”
《算法竞赛快冲300题》将于2024年出版,是《算法竞赛》的辅助练习册。 所有题目放在自建的OJ New Online Judge。 用C/C、Java、Python三种语言给出代码,以中低档题为主,适合入门、进阶。 文章目录 题目描述题解C代码Java代码Python代码 “ 最…...

mysql的主键选择
一.没有定义主键有什么问题 如果定义了主键,那么InnoDB会使用主键作为聚簇索引如果没有定义主键,那么会使用第一非空的唯一索引(NOT NULL and UNIQUE INDEX)作为聚簇索引如果既没有主键也找不到合适的非空索引,那么In…...
Eureka 学习笔记1:服务端实例缓存
版本 awsVersion ‘1.11.277’ 缓存类型registryConcurrentHashMap<String, Map<String, Lease<InstanceInfo>>>AbstractInstanceRegistry成员变量readWriteCacheMapLoadingCacheResponseCacheImpl成员变量readOnlyCacheMapConcurrentMap<Key, Value>…...
vue : 无法加载文件 C:\Users\86182\AppData\Roaming\npm\vue.ps1,因为在此系统上禁止运行脚本。
windows11: PS E:\VueProjects> vue vue : 无法加载文件 C:\Users\86182\AppData\Roaming\npm\vue.ps1,因为在此系统上禁止运行脚本。有关详细信息,请参阅 https:/ go.microsoft.com/fwlink/?LinkID135170 中的 about_Execution_Policie…...

FLinkCDC读取MySQl时间戳时区相关问题解决汇总
FlinkCDC时间问题timestamp等https://blog.csdn.net/qq_30529079/article/details/127809317 FLinkCDC读取MySQl中的日期问题https://blog.csdn.net/YPeiQi/article/details/130265653 关于flink1.11 flink sql使用cdc时区差8小时问题https://blog.csdn.net/weixin_44762298/…...
第三篇-Tesla P40+CentOS7+CUDA 11.7 部署实践
硬件环境 系统:CentOS-7 CPU: 14C28T 显卡:Tesla P40 24G 准备安装 驱动: 515 CUDA: 11.7 cuDNN: 8.9.2.26 安装依赖 yum clean all yum update yum install -y gcc gcc-c pciutils kernel-devel-$(uname -r) kernel-headers-$(uname -r)查看GPU信息…...

AC+FIT(瘦AP)配置浅谈
FIT ensp实验材料 :pc、路由器、三层交换机、二层交换机、ac、ap 保证连通性: 根据ac与ap设计好的ip配置,使之可以通讯 ac与ap可以实现跨网段管理 1、设置三层交换机的vlan 与vlanif信息 dhcp enable //开启dhcp ip pool forap //…...

【Python】PySpark 数据计算 ② ( RDD#flatMap 方法 | RDD#flatMap 语法 | 代码示例 )
文章目录 一、RDD#flatMap 方法1、RDD#flatMap 方法引入2、解除嵌套3、RDD#flatMap 语法说明 二、代码示例 - RDD#flatMap 方法 一、RDD#flatMap 方法 1、RDD#flatMap 方法引入 RDD#map 方法 可以 将 RDD 中的数据元素 逐个进行处理 , 处理的逻辑 需要用外部 通过 参数传入 map…...

二叉树题目:左叶子之和
文章目录 题目标题和出处难度题目描述要求示例数据范围 解法一思路和算法代码复杂度分析 解法二思路和算法代码复杂度分析 题目 标题和出处 标题:左叶子之和 出处:404. 左叶子之和 难度 3 级 题目描述 要求 给你二叉树的根结点 root \texttt{ro…...
Spark SQL报错: Task failed while writing rows.
错误 今天运行 Spark 任务时报了一个错误,如下所示: WARN scheduler.TaskSetManager: Lost task 9.0 in stage 3.0 (TID 69, xxx.xxx.xxx.com, executor 3): org.apache.spark.SparkException: Task failed while writing rows.at org.apache.spark.sq…...

Linux系统下U盘打不开: No application is registered as handling this file
简述 系统是之前就安装好使用的Ubuntu14.04,不过由于某些原因只安装到了机械硬盘中;最近新买了一块固态硬盘,所以打算把Ubuntu系统迁移到新的固态硬盘上; 当成功的迁移了系统之后发现其引导有点问题,导致多个系统启动不…...

07 定时器处理非活动连接(上)
07 定时器处理非活动连接(上) 基础知识 非活跃,是指客户端(这里是浏览器)与服务器端建立连接后,长时间不交换数据,一直占用服务器端的文件描述符,导致连接资源的浪费。 定时事件&a…...

python——案例四:判断字符串中的元素组成
案例四:判断字符串中的元素组成str"Hello World! 666" print(str.isalnum()) #判读所有的字符都是数字或者是字母 print(str.isalpha()) #判读所有的字符都是字母 print(str.isdigit()) #判读所有的字符都是数字 print(str.islower()) #判读所有的字符都是…...

一起学算法(插入排序篇)
概念: 插入排序(inertion Sort)一般也被称为直接插入排序,是一种简单的直观的排序算法 工作原理:将待排列元素划分为(已排序)和(未排序)两部分,每次从&…...

JVM基础篇-本地方法栈与堆
JVM基础篇-本地方法栈与堆 本地方法栈 什么是本地方法? 本地方法即那些不是由java层面实现的方法,而是由c/c实现交给java层面进行调用,这些方法在java中使用native关键字标识 public native int hashCode()本地方法栈的作用? 为本地方法提供内存空…...

防雷保护区如何划分,防雷分区概念LPZ介绍
在防雷设计中,很重要的一点就是防雷分区的划分,只有先划分好防雷区域等级,才好做出比较好的防雷器设计方案。 因为标准对不同区安装的防雷浪涌保护器要求是不一样的。 那么,防雷保护区是如何划分的呢? 如上图所示&…...
随手笔记——3D−3D:ICP求解
随手笔记——3D−3D:ICP求解 使用 SVD 求解 ICP使用非线性优化来求解 ICP 原理参见 https://blog.csdn.net/jppdss/article/details/131919483 使用 SVD 求解 ICP 使用两幅 RGB-D 图像,通过特征匹配获取两组 3D 点,最后用 ICP 计算它们的位…...
Python调用各大机器翻译API大全
过去的二三年中,我一直关注的是机器翻译API在自动化翻译过程中的应用,包括采用CAT工具和Python编程语言来调用机器翻译API,然后再进行译后编辑,从而达到快速翻译的目的。 然而,我发现随着人工智能的发展,很…...

重生之我要学C++第六天
这篇文章的主要内容是const以及权限问题、static关键字、友元函数和友元类,希望对大家有所帮助,点赞收藏评论支持一下吧! 更多优质内容跳转: 专栏:重生之C启程(文章平均质量分93) 目录 const以及权限问题 1.const修饰…...

SpringBoot中ErrorPage(错误页面)的使用--【ErrorPage组件】
SpringBoot系列文章目录 SpringBoot知识范围-学习步骤–【思维导图知识范围】 文章目录 SpringBoot系列文章目录本系列校训 SpringBoot技术很多很多环境及工具:必要的知识深层一些的知识 上效果图在Spring Boot里使用ErrorPage还要注意的是 配套资源作业ÿ…...

Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...

【第二十一章 SDIO接口(SDIO)】
第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

C# 类和继承(抽象类)
抽象类 抽象类是指设计为被继承的类。抽象类只能被用作其他类的基类。 不能创建抽象类的实例。抽象类使用abstract修饰符声明。 抽象类可以包含抽象成员或普通的非抽象成员。抽象类的成员可以是抽象成员和普通带 实现的成员的任意组合。抽象类自己可以派生自另一个抽象类。例…...
【生成模型】视频生成论文调研
工作清单 上游应用方向:控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...
NPOI操作EXCEL文件 ——CAD C# 二次开发
缺点:dll.版本容易加载错误。CAD加载插件时,没有加载所有类库。插件运行过程中用到某个类库,会从CAD的安装目录找,找不到就报错了。 【方案2】让CAD在加载过程中把类库加载到内存 【方案3】是发现缺少了哪个库,就用插件程序加载进…...
LangChain 中的文档加载器(Loader)与文本切分器(Splitter)详解《二》
🧠 LangChain 中 TextSplitter 的使用详解:从基础到进阶(附代码) 一、前言 在处理大规模文本数据时,特别是在构建知识库或进行大模型训练与推理时,文本切分(Text Splitting) 是一个…...
多元隐函数 偏导公式
我们来推导隐函数 z z ( x , y ) z z(x, y) zz(x,y) 的偏导公式,给定一个隐函数关系: F ( x , y , z ( x , y ) ) 0 F(x, y, z(x, y)) 0 F(x,y,z(x,y))0 🧠 目标: 求 ∂ z ∂ x \frac{\partial z}{\partial x} ∂x∂z、 …...
2025年低延迟业务DDoS防护全攻略:高可用架构与实战方案
一、延迟敏感行业面临的DDoS攻击新挑战 2025年,金融交易、实时竞技游戏、工业物联网等低延迟业务成为DDoS攻击的首要目标。攻击呈现三大特征: AI驱动的自适应攻击:攻击流量模拟真实用户行为,差异率低至0.5%,传统规则引…...

RabbitMQ 各类交换机
为什么要用交换机? 交换机用来路由消息。如果直发队列,这个消息就被处理消失了,那别的队列也需要这个消息怎么办?那就要用到交换机 交换机类型 1,fanout:广播 特点 广播所有消息:将消息…...
学习 Hooks【Plan - June - Week 2】
一、React API React 提供了丰富的核心 API,用于创建组件、管理状态、处理副作用、优化性能等。本文档总结 React 常用的 API 方法和组件。 1. React 核心 API React.createElement(type, props, …children) 用于创建 React 元素,JSX 会被编译成该函数…...