【图论】1 (最小生成树虚拟点思想)C.戴森球计划 题解

一. 题目

题目描述

题目描述

输入输出格式

输入输出格式

样例

样例1

样例1

样例2 & 样例解释

样例2 & 样例解释

数据范围

数据范围

二. 思路

对于前20%数据 解法

因为保证了 x i = 1 x_i = 1 xi=1,也就是说这些点都在 x = 1 x = 1 x=1 这条直线上。

那么最优解必定是在 c i c_i ci 最小的点上建发电站,然后把这些点之间全部联通即可。

即最终答案 a n s = min ⁡ 1 ≤ i ≤ n c i + max ⁡ 1 ≤ i ≤ n y i − min ⁡ 1 ≤ i ≤ n y i ans = \min_{1 \leq i \leq n}c_i + \max_{1 \leq i \leq n}y_i - \min_{1 \leq i \leq n} y_i ans=1inminci+1inmaxyi1inminyi

可见,我们要枚举 1 1 1 n n n ,所以时间复杂度为 O ( n ) O(n) O(n)

对于前70%数据 解法

思路分析

因为50%的数据没有什么特殊的地方(至少作者没有想到),所以直接从70%的数据入手。

思考: k i = 1 k_i = 1 ki=1 ,也就是点之间的连线每条边的单位花费为 1 + 1 = 2 1+1=2 1+1=2 ,而 1 0 8 ≤ c i ≤ 1 0 9 10^8 \leq c_i \leq 10^9 108ci109 很大,并且在 n ≤ 2000 n \leq 2000 n2000 的情况下,我们发现连线的花费往往小于构建发电站的花费。所以容易得出贪心策略 c i c_i ci 最小的点建发电站,其他点都与这个点联通

这个问题就等价于要把图上的每一个点都联通,并且花费最小

先考虑如何联通每一个点:构建一棵树,共有 n n n 个点和 n − 1 n-1 n1 条边。

其次要让花费小:这不就是最小生成树吗?!

具体实现

我们先把 n n n 个点之间两两连线,每条边的权值为该边的花费,构建一个完全图,然后对这张图 跑Kruskal或Prim(最小生成树) 即可。

对于100%数据 解法

发现100%的数据与70%的数据对比, k i k_i ki c i c_i ci 的取值范围更广泛,所以不一定只有一个发电站是最优解

那么按照70%数据的思路,我们对于每一个发电站,都会构建出一棵最小生成树,但一棵不一定涵盖所有点。即这张图变成了一个最小生成树组成的森林

这样的话,我们没法枚举每个发电站再构建最小生成树。能不能把这些树合在一起呢?

这里,我们引入 “虚拟点思想”,也叫做 “超级零点” 。也就是新增0号(或不在范围内的)点,并把它向其他点都连一条边,边的权值为在与其相连的点构建发电站的花费

这样,我们就可以对这个图跑最小生成树即可。因为最小生成树一定会连向虚拟点,所以至少会构建一个发电站,思路可行。

三. 代码实现

20pts 解法

#include <bits/stdc++.h>
using namespace std;
const int N = 2055;
long long id,n,k[N],x[N],y[N],maxx,minn=1e17,ress=1e17;
long long c[N],f[N],res = 1e17,ans = 0,cnt;
struct node
{long long u,v,w;
}a[N*N*2];
int main()
{freopen("electricity.in","r",stdin);freopen("electricity.out","w",stdout);cin >> id;cin >> n;for (int i=1;i<=n;i++){scanf("%lld%lld",&x[i],&y[i]);}for (int i=1;i<=n;i++){scanf("%lld",&c[i]);}for (int i=1;i<=n;i++){scanf("%lld",&k[i]);}if (1 <= id && id <= 4){for (int i=1;i<=n;i++){maxx = max(maxx,y[i]);minn = min(minn,y[i]);ress = min(ress,c[i]);}cout<<(maxx-minn)*2+ress;return 0;}return 0;
}

70pts 解法

#include <bits/stdc++.h>
using namespace std;
const int N = 2005;
long long id,n,k[N],x[N],y[N],maxx,minn=1e17,ress=1e17;
long long c[N],f[N],res = 1e17,ans = 1e17,cnt;
struct node
{long long u,v,w;
}a[N*N];
long long zabs(long long s)
{if (s > 0) return s;return -s;
}
long long dis(long long a,long long b)
{return zabs(x[a]-x[b])+zabs(y[a]-y[b]);
}
void add(long long h,long long b,long long c)
{a[++cnt].u = h;a[cnt].v = b;a[cnt].w = c;
}
bool cmp(node x,node y)
{return x.w < y.w;
}
long long fnd(int x)
{if (x == f[x]) return x;return f[x] = fnd(f[x]);
}
int main()
{freopen("electricity.in","r",stdin);freopen("electricity.out","w",stdout);cin >> id;cin >> n;for (int i=1;i<=n;i++){scanf("%lld%lld",&x[i],&y[i]);}for (int i=1;i<=n;i++){scanf("%lld",&c[i]);}for (int i=1;i<=n;i++){scanf("%lld",&k[i]);}ans = 1e17;for (int i=1;i<=n;i++){ans = mins(ans,c[i]);}for (int i=1;i<n;i++){for (int j=i+1;j<=n;j++){add(j,i,dis(i,j)*(k[i]+k[j]));add(i,j,dis(i,j)*(k[i]+k[j]));}}sort(a+1,a+cnt+1,cmp);long long tot = 0;for (int j=1;j<=n;j++){f[j] = j;}for (int j=1;j<=cnt;j++){long long p1 = fnd(f[a[j].u]);long long p2 = fnd(f[a[j].v]);if (f[p1] == f[p2]) continue;f[p1] = fnd(f[p2]);ans += a[j].w;tot++;if (tot+1 == n) break;}cout<<ans;return 0;
}

100pts 解法

#include <bits/stdc++.h>
using namespace std;
const int N = 2055;
long long id,n,k[N],x[N],y[N],maxx,minn=1e17,ress=1e17;
long long c[N],f[N],res = 1e17,ans = 0,cnt;
struct node
{long long u,v,w;
}a[N*N*2];
long long zabs(long long s)
{if (s > 0) return s;return -s;
}
long long dis(long long a,long long b)
{return zabs(x[a]-x[b])+zabs(y[a]-y[b]);
}
void add(long long h,long long b,long long c)
{a[++cnt].u = h;a[cnt].v = b;a[cnt].w = c;
}
bool cmp(node x,node y)
{return x.w < y.w;
}
long long fnd(int x)
{if (x == f[x]) return x;return f[x] = fnd(f[x]);
}
int main()
{freopen("electricity.in","r",stdin);freopen("electricity.out","w",stdout);cin >> id;cin >> n;for (int i=1;i<=n;i++){scanf("%lld%lld",&x[i],&y[i]);}for (int i=1;i<=n;i++){scanf("%lld",&c[i]);}for (int i=1;i<=n;i++){scanf("%lld",&k[i]);}ans = 0;//构图for (int i=1;i<n;i++){for (int j=i+1;j<=n;j++){add(j,i,dis(i,j)*(k[i]+k[j]));add(i,j,dis(i,j)*(k[i]+k[j]));}}//虚拟点构建for (int i=1;i<=n;i++){add(n+1,i,c[i]);add(i,n+1,c[i]);}sort(a+1,a+cnt+1,cmp);long long tot = 0;for (int j=1;j<=n+1;j++){f[j] = j;}//Kruskal最小生成树for (int j=1;j<=cnt;j++){long long p1 = fnd(f[a[j].u]);long long p2 = fnd(f[a[j].v]);if (f[p1] == f[p2]) continue;f[p1] = fnd(f[p2]);ans += a[j].w;tot++;if (tot == n) break;}cout<<ans;return 0;
}

四. 总结

这道图论题在CSP-J模拟赛放了T3,感觉略难(最小生成树和虚拟点思想略有超纲),但不引进“虚拟点思想”的70分给的很足。总体来说是一道练习最小生成树和虚拟点思想的好题。

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

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

相关文章

4.人员管理模块(开始预备工作)——帝可得管理系统

目录 前言一、需求分析1.页面原型2.创建SQL 二、使用若依框架生成前后端代码1.添加目录菜单2.添加数据字典3.配置代码生成信息4.下载代码并导入项目5.快速导入方法 三、 总结 前言 提示&#xff1a;本篇讲解人员管理模块的开发的预备工作&#xff0c;包括需求分析、生成代码、…

Android 10.0 系统framework层控制传感器开启和禁用功能实现

1.前言 在10.0的系统rom定制化开发中,对于系统传感器,光线,距离,重力等传感器的使用过程中,在某些产品 做定制的时候,需要控制这些传感器的使用情况,所以就需要看下怎么样限制传感器的使用功能, 2.系统framework层控制传感器开启和禁用功能实现的核心类 frameworks\…

uniapp+Android面向网络学习的时间管理工具软件 微信小程序

目录 项目介绍支持以下技术栈&#xff1a;具体实现截图HBuilderXuniappmysql数据库与主流编程语言java类核心代码部分展示登录的业务流程的顺序是&#xff1a;数据库设计性能分析操作可行性技术可行性系统安全性数据完整性软件测试详细视频演示源码获取方式 项目介绍 用户功能…

最新版本SkyWalking【10.1.0】部署

这里写目录标题 前言前置条件启动Skywalking下载解压启动说明 集成Skywalking Agent下载Agent在IDEA中添加agent启动应用并访问SpringBoot接口 说明 前言 基于当前最新版10.1.0搭建skywalking 前置条件 装有JDK11版本的环境了解SpringBoot相关知识 启动Skywalking 下载 地…

golang grpc进阶

protobuf 官方文档 基本数据类型 .proto TypeNotesGo Typedoublefloat64floatfloat32int32使用变长编码&#xff0c;对于负值的效率很低&#xff0c;如果你的域有可能有负值&#xff0c;请使用sint64替代int32uint32使用变长编码uint32uint64使用变长编码uint64sint32使用变长…

Linux:无法为立即文档创建临时文件: 设备上没有空间

虚拟机磁盘空间不足解决记录 1、问题描述2、问题解决 1、问题描述 在命令行输入命令按Tab键时出现如下报错&#xff1a; 很明显&#xff0c;设备上没有空间&#xff0c;即磁盘空间不足。通过命令查看具体情况如下&#xff1a; df -h2、问题解决 首先想到的是虚拟机扩容。关机虚…

numpy 逻辑运算方法介绍

在 NumPy 中&#xff0c;逻辑运算方法用于对数组中的元素进行逻辑操作&#xff0c;通常用于布尔数组&#xff0c;也可用于数值数组&#xff0c;非零值视为 True&#xff0c;零值视为 False。常见的逻辑运算方法有&#xff1a; 1. numpy.logical_and 逐元素进行逻辑与运算&…

每日学习一个数据结构-树

文章目录 树的相关概念一、树的定义二、树的基本术语三、树的分类四、特殊类型的树五、树的遍历六、树的应用场景 树的遍历一、前序遍历二、中序遍历三、后序遍历使用java代码实现遍历总结 树的相关概念 树是一种重要的非线性数据结构&#xff0c;在计算机科学中有着广泛的应用…

C++IO流

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 CIO流 收录于专栏 [C进阶学习] 本专栏旨在分享学习C的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 1. C语言的输入与输出 2. 流是什…

(PyTorch) 深度学习框架-介绍篇

前言 在当今科技飞速发展的时代&#xff0c;人工智能尤其是深度学习领域正以惊人的速度改变着我们的世界。从图像识别、语音处理到自然语言处理&#xff0c;深度学习技术在各个领域都取得了显著的成就&#xff0c;为解决复杂的现实问题提供了强大的工具和方法。 PyTorch 是一个…

大数据分析入门概述

大数据分析入门概述 本文旨在为有意向学习数据分析、数据开发等大数据方向的初学者提供一个学习指南&#xff0c;当然如果你希望通过视频课程的方式快速入门&#xff0c;B站UP主戴戴戴师兄的课程质量很高&#xff0c;并且适合初学者快速入门。本文的目的旨在为想要了解大数据但…

C语言基础(7)之操作符(1)(详解)

目录 1. 各种操作符介绍 1.1 操作符汇总表 2. 移位操作符 2.1 移位操作符知识拓展 —— 原码、反码、补码 2.2 移位操作符讲解 2.2.1 右移操作符 ( >> ) 2.2.2 左移操作符 ( << ) 3. 位操作符 3.1 & (按位与) 3.2 | (按位或) 3.3 ^ (按位异或) 3.4…

vue3 父子组件调用

vue3 父子组件调用 父组件调用子组件方法 子组件使用defineExpose将方法抛出 父组件定义 function&#xff0c;子组件通过 defineExpose 暴露方法&#xff0c;父组件通过 ref 获取子组件实例&#xff0c;然后通过 ref 获取子组件方法。 // 父组件 <template><div>…

探索Cherry键盘的FN+F9游戏模式与Ctrl+Fn功能

简言 在电竞和日常办公领域&#xff0c;Cherry键盘以其卓越的按键反馈和耐用性而闻名。今天&#xff0c;我们将深入探讨Cherry键盘的两个独特功能&#xff1a;FNF9游戏模式和CtrlFn锁定功能。 介绍 FNF9&#xff1a;一键切换游戏模式 功能介绍&#xff1a; FNF9是Cherry键…

零基础编程从哪开始学?

目录 第一、零基础怎么学习编程&#xff1f;第二、什么书籍、教程或者博主比较好 第一、零基础怎么学习编程&#xff1f; 1. 确定目的而不是语言。 首先&#xff0c;你要知道你学习编程是为了什么目的&#xff0c; 或者说你学习编程的初心是什么&#xff1f; 可能你对游戏开发…

JMeter源码解析之JMeter命令行新增命令

JMeter源码解析之JMeter命令行新增命令 需求描述 需要新增一条命令&#xff0c;能够在JMeter命令行中能够展示输入对应的JMeter命令&#xff0c;能够展示对应的命令信息 查看命令效果如下&#xff1a; apache-jmeter-5.1\bin>jmeter --? Copyright © 1999-2024 The …

深度学习每周学习总结J1(ResNet-50算法实战与解析 - 鸟类识别)

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制 目录 0. 总结1. 设置GPU2. 导入数据及处理部分3. 划分数据集4. 模型构建部分5. 设置超参数&#xff1a;定义损失函数&#xff0c;学习率&a…

Python 解析 html

一、场景分析 假设有如下 html 文档&#xff1a; 写一段 python 脚本&#xff0c;解析出里面的数据&#xff0c;包括经度维度。 <div classstorelist><ul><li lng"100.111111" lat"10.111111"><h4>联盟店1</h4><p>…

资源网站分享

云计算文档中心各个方向(云计算 大数据 路由器 交换机 无线 物联网 安全 光模块 智能管理与运维 移动通信 服务器 存储 PON ICG信息通信 EPCN网关 License Server 其他产品 智能终端 传输产品 云简网络 商用终端 ALGC SMB 产品)云计算-云计算产品-云计算解决方案-新华三集团-H3…

【2024】基于mysqldump的数据备份与恢复

基于mysqldump备份与恢复 mysqldump是一个用于备份 MySQL 数据库的实用工具。 它可以将数据库的结构&#xff08;如数据库、表、视图、存储过程等的定义&#xff09;和数据&#xff08;表中的记录&#xff09;导出为文本文件&#xff0c;这些文本文件可以包含 SQL 语句&#…