Luogu7417 [USACO21FEB] Minimizing Edges P 做题记录

news/2025/2/13 11:06:05/文章来源:https://www.cnblogs.com/Sktn0089/p/18712735

很普通但是很强大的贪心题。link

\(dis_{u, 0/1}\) 表示 \(1\to u\) 的最短奇 / 偶路径长度,原题可以转化为 \(G'\)\(G\)\(dis_{1\dots n, 0 / 1}\) 不变,求 \(G'\) 的最小边数。

先 BFS 求出 \(dis_{u, 0 / 1}\)。设 \(x = \min(dis_{u, 0}, dis_{u, 1}), y = \max(dis_{u, 0}, dis_{u, 1})\),那么可以将 \(u\) 视为二维平面上的点 \((x, y)\)

观察连边合法的条件。对于一个点 \((x, y)\),它合法当且仅当满足以下条件之一:

  • \((x - 1, y - 1)\) 有连边。

  • 同时与 \((x - 1, y + 1)\)\((x + 1, y - 1)\) 有连边。

  • \(y = x + 1\),这些点自连。

我们按照 \(x + y\) 从小到大一层一层考虑。第一个条件相当于和上面一层对应的点连边,第二个条件相当于和相邻两个点连边。

\((x, x + 1)\) 可以自连。具体的,\(k\) 个点 \((x, x + 1)\) 通过两两之间连边可以自行合法化,代价为 \(\lceil \frac k2 \rceil\)

\((x, x + 1)\) 的条件特殊考虑:必须与上一层的点 或者 \((x - 1, x + 2)\) 连边。若与 \((x - 1, x + 2)\) 连边,还需要自连合法。

所以对于每一层,可以按照 \(x\) 从小到大的顺序处理每个点。为了方便,令可以与上一层连边的点为黑点,否则为白点。

白点必须和相邻两个点连边,所以我们在处理的时候,记录一下上一个点传下来的连边需求数量。

倘若遇到黑点,我们可以直接终结连边需求。但是我们有贪心策略:连边需求能往后传就往后传,原因:

  • 若直接终结,和往后传的代价相同。

  • 若下一个点是白点,也会产生连边需求,终结无效。

  • 到了边界点 \((x, x + 1)\),若有连边需求,可以省掉其与上一层的点的连边代价,改为每个点 \(\frac 12\) 代价(注意其与相邻点连边的代价不是算在自己,而是算在那个相邻点处的)。

时间复杂度 \(\mathcal O(n + m)\)


这道题的第一步是数形结合,将图上问题转化为平面图上的问题。

然后需要观察模型,将每个点的条件转化为严格处于平面图上的条件。这里我一开始想到了和上一层连边,但是没有注意到若不与 \((x - 1, y - 1)\) 连边则必须与 \((x - 1, y + 1)\)。换言之,我认为其可以与纵坐标 \(> y + 1\) 的点连边。

如果观察到了这个更严格的条件,那么就很显然可以按照 \(x + y\) 来分层,最后贪心。

贪心的时候细节也有点多,写代码要理清思路。


点击查看代码
#include <bits/stdc++.h>
namespace Initial {#define ll long long#define ull unsigned ll#define fi first#define se second#define mkp make_pair#define pir pair <ll, ll>#define pb push_back#define i128 __int128using namespace std;const ll maxn = 2e5 + 10, inf = 1e9, mod = 998244353, iv = mod - mod / 2;ll power(ll a, ll b = mod - 2, ll p = mod) {ll s = 1;while(b) {if(b & 1) s = 1ll * s * a %p;a = 1ll * a * a %p, b >>= 1;} return s;}template <class T>const inline ll pls(const T x, const T y) { return x + y >= mod? x + y - mod : x + y; }template <class T>const inline void add(T &x, const T y) { x = x + y >= mod? x + y - mod : x + y; }template <class T>const inline void chkmax(T &x, const T y) { x = x < y? y : x; }template <class T>const inline void chkmin(T &x, const T y) { x = x < y? x : y; }
} using namespace Initial;namespace Read {char buf[1 << 22], *p1, *p2;// #define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, (1 << 22) - 10, stdin), p1 == p2)? EOF : *p1++)template <class T>const inline void rd(T &x) {char ch; bool neg = 0;while(!isdigit(ch = getchar()))if(ch == '-') neg = 1;x = ch - '0';while(isdigit(ch = getchar()))x = (x << 1) + (x << 3) + ch - '0';if(neg) x = -x;}
} using Read::rd;ll t, n, m, dis[maxn][2], q[maxn][2], l, r;
vector <ll> to[maxn], vec[maxn << 1];
ll ans, c[maxn], bin[maxn]; bool vis[maxn];void solve() {rd(n), rd(m); ans = 0;for(ll i = 1; i <= n; i++) to[i].clear();for(ll i = 0; i <= 3 * n; i++) vec[i].clear();for(ll i = 1; i <= m; i++) {ll u, v; rd(u), rd(v);to[u].pb(v), to[v].pb(u);} q[l = r = 1][0] = 1, q[1][1] = 0;for(ll i = 1; i <= n; i++) dis[i][0] = dis[i][1] = -1;dis[1][0] = 0;while(l <= r) {ll u = q[l][0], z = q[l++][1];for(ll v: to[u])if(dis[v][z ^ 1] == -1) {dis[v][z ^ 1] = dis[u][z] + 1;q[++r][0] = v, q[r][1] = z ^ 1;}}if(dis[1][1] == -1) return printf("%lld\n", n - 1), void();for(ll i = 1; i <= n; i++)vec[dis[i][0] + dis[i][1]].pb(min(dis[i][0], dis[i][1]));for(ll d = 1; d <= 3 * n - 2; d += 2) {if(vec[d].empty()) continue;if(d > 1)for(ll x: vec[d - 2]) vis[x] = true;sort(vec[d].begin(), vec[d].end());for(ll x: vec[d]) ++bin[x];vec[d].erase(unique(vec[d].begin(), vec[d].end()), vec[d].end());for(ll x: vec[d]) {ll y = d - x;if(x == 0) {if(y == 1) ++ans;continue;}if(y == x + 1) {ll tmp = min(bin[x], c[x - 1]);if(vis[x - 1]) ans += c[x - 1] + bin[x] - tmp + (tmp + 1) / 2;else ans += max(bin[x], c[x - 1]) + (bin[x] + 1) / 2; } else if(vis[x - 1]) {c[x] = min(c[x - 1], bin[x]);if(bin[x + 1]) ans += max(c[x - 1], bin[x]);else ans += c[x - 1] + bin[x];} else {ans += max(bin[x], c[x - 1]);c[x] = bin[x];}}for(ll x: vec[d]) c[x] = bin[x] = 0;if(d > 1)for(ll x: vec[d - 2]) vis[x] = false;} printf("%lld\n", ans);
}int main() {rd(t); while(t--) solve();return 0;
}

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

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

相关文章

linkedhashmap和hashmap区别

https://docs.pingcode.com/ask/67278.htmllinkedhashmap和hashmap区别2023-12-26 261 百科 LinkedHashMap和HashMap是Java中用于存储键值对的数据结构,它们之间的主要区别在于对键值对的顺序管理和性能特征。LinkedHashMap保留了键值对的插入顺序,而HashMap则不保证顺序。Li…

secureCRT 个人配置

前言secureCRT 是一款比较简介轻量的远程工具,支持ssh、串口登录等操作。下面的内容是根据本人操作习惯做的一些配置,留作后续再次安装时参考。 配置1. 修改鼠标功能 设置 -> 全设置 -> 外观 -> 鼠标功能去掉勾选 粘贴(P)用鼠标的xx键,默认是鼠标右键,但是查询系统…

看板工具与跨团队协作:从流程标准化到数据驱动决策

通过这些策略,看板工具可以有效提升跨团队协作效率,确保项目顺利进行。跨团队协作效率优化可以通过看板工具实现,以下是一些关键步骤和策略: 1. 选择合适的看板工具 ● 工具选择:根据团队需求选择适合的看板工具,如banlikanban、Trello、Asana、Monday.com等。 ● 功能评…

MINE类型

1、什么是MIME类型MIME(Multipurpose Internet Mail Extensions)类型是在互联网上用于标识文件类型的标准方式。它在很多应用中得到了广泛的应用,例如电子邮件、Web浏览器和Web服务器等。MIME类型是由两部分组成的,第一部分是媒体类型(media type),用来表示文件的大类别…

解决微信小程序原生云开发退款报错“特约子商户商户号未授权服务商的产品权限”的问题

背景:微信小程序云开发支付没问题,退款时就会报这个错。 现象: 解决方法流程: 1、打开微信小程序开发者工具上面的云开发界面: 2、进入设置: 3、其他设置: 需要授权退款API权限,我这里已经授权了,未授权的话会有授权按钮,点击后会提示等待商户审核 4、我们来到微信支…

探索ChatGPT背后的前端黑科技

由于图片和格式解析问题,可前往 阅读原文在人工智能与互联网技术飞速发展的今天,像ChatGPT这样的智能对话系统已经成为科技领域的焦点。它不仅能够进行自然流畅的对话,还能以多种格式展示内容,为用户带来高效且丰富的交互体验。然而,这些令人惊叹的功能背后,离不开前端技…

OTA软件升级管理系统

OTA(空中下载技术)是通过空中下载的方式对车辆中的软件进行远程升级。经纬恒润OTA软件升级管理系统基于软件架构、应用架构、业务架构和技术架构,为整车提供云-管-端-屏完整OTA解决方案,可靠地完成系统更新、软件升级、功能迭代和安全漏洞修复等功能。同时支持固件升级(FOTA…

深度学习经典 - 鱼书 - 《深度学习入门:基于Python的理论与实现》 - PDF免费下载

深度学习经典“鱼书”,下载地址:https://pdfs.top/book/深度学习入门:基于Python的理论与实现.html。本书深入浅出地介绍了深度学习的原理,使用Python3从零开始构建深度学习模型。书中详细讲解了神经网络、误差反向传播法、卷积神经网络等核心技术,并探讨了深度学习在自动…

DeepSeek 相关知识学习和整理ing...

【硬件相关】 HBM3e:HBM3e是HBM(高带宽内存)技术的迭代升级版本,属于HBM3的扩展。它采用3D堆叠封装技术,将多个DRAM芯片垂直堆叠,通过硅互连通道传输数据,大幅提升带宽和容量,同时降低功耗。 迭代背景:HBM系列从第一代(HBM)到第五代(HBM3e)持续升级,每一代都提高…

打靶记录27——Tre

靶机: https://www.vulnhub.com/entry/tre-1,483/ 下载(镜像):https://download.vulnhub.com/tre/Tre.zip 难度:中目标:获得 Root 权限 + Flag攻击方法:主机发现 端口扫描 信息收集 进阶路径枚举 EXP 代码改造 突破边界方法1 突破边界方法2 突破边界方法3 权限提升主机发…

7. Docker 容器数据卷的使用(超详细的讲解说明)

7. Docker 容器数据卷的使用(超详细的讲解说明) @目录7. Docker 容器数据卷的使用(超详细的讲解说明)1. Docker容器数据卷概述2. Docker 容器数据卷的使用演示:2.1 宿主 和 容器之间映射添加容器卷2.2 容器数据卷 读写规则映射添加说明2.3 容器数据卷的继承和共享3. 最后:坑:…

到底值不值得本地部署残血版DeepSeek?一文说清!教你如何白嫖满血版DeepSeek

一、介绍最近一段时间,DeepSeek 备受关注,夏天也向身边朋友推荐。但它常无法使用,原因是受到大规模恶意攻击,且 IP 地址在美国。 通过以下网站可以查看DeepSeek网站状态: status.deepseek.com/ 可以发现,最近标红的就是故障中​若遇服务器繁忙提示,大概率是被攻击了,并…