洛谷博客:https://www.luogu.com.cn/article/5n200x7y

Link - P13823

讨论区中有很多有用的 hack,没过的话可以去看看。


每个点都可以换到其所在弱连通分量的最大点权,这是毋庸置疑的。

为了方便陈述,下文中记当前弱连通分量中点权最大的点为 xxx,点 uuu 的最终答案为 ans[u]ans[u]ans[u]

考虑一个点 uuu 的交换过程,可能有以下几种情况:

  1. xxx 本身,不用交换。
  2. uuu 能直接到达 xxx,交换次数为 111 次。
  3. uuu 无法到达 xxx,那么需要先找到一个 uuu 能到达,且可以到达 xxx 的点 vvv,然后通过这个点“中转”,交换次数为 ans[v]+1ans[v]+1ans[v]+1 次。

不难想到,权值在不断转移的过程其实可以看成联通分量中点 xxx 通过一条路径走到一些待更新点的过程,我们想求最小操作次数其实就是求 xxx 到其他点的最短路。现在的问题是如何合理安排边的方向和权值。


先考虑边的方向。

对于情况二,如果建原图的反图,那么方向显然就对上了(可以从 xxx 向待操作的点走)。

思考对于情况三怎么办,我们定义“正向边”为与原图方向相反的边,“反向边”为与原图方向相同的边。

注:这样定义正向、反向边是相对于点 xxx 而言,看起来方便一些。

发现“中转”过程其实可以用若干套正向边(与原图方向相反)和反向边(和原图方向相同)来刻画。具体地,假设当前点为 uuu,那么转移路径应该是 x→正向边v→反向边ux \xrightarrow{\text{正向边}} v \xrightarrow{\text{反向边}} ux正向边v反向边u


下面考虑边的权值,或者说考虑如何求答案。

首先想到的是可以每中转一次答案就加 111。这显然是对的,但太麻烦了,因为每个点的来源都不同,也不确定会经过几次中转,过程中还要维护边的方向等。

考虑一种更简单的分层图方法:一层是原图,另一层是反图,这些边权都是 000。然后上下每个对应的点建一个边权为 111 的双向边(相当于把中转时的花费放到层与层之间的转换上)。

然后,我们找出所有弱连通分量中点权最大的点及其在下一层的对应点作为起点,都跑一遍最短路,因为不能确定从哪个起点走一定最优。

uuu 在下一层中的点为 u′u'u,到 uuu 的最短路为 dis[u]dis[u]dis[u],则 ans[u]=min⁡{dis[u],dis[u′]}ans[u]=\min\{dis[u], dis[u']\}ans[u]=min{dis[u],dis[u]}

但尝试发现这样会出问题:有的结点答案少 111,有的又没少,这是为什么呢?不难发现,是因为题目无论如何都需要至少一次操作,但按照上面的方法,如果 uuu 能直接到 xxx,那么 dis[u]=0dis[u]=0dis[u]=0。这显然不对,那么对于能直接到达 xxx 的点把答案加一即可。

综上,记 uuu 点权为 val[u]val[u]val[u]uuu 所在连通块编号为 pos[u]pos[u]pos[u],连通块 ppp 中的最大点权为 mx[p]mx[p]mx[p],答案为:

ans[u]={0val[u]=mx[pos[u]]min⁡{dis[u],dis[u′]}otherwiseans[u] = \begin{cases} 0 & val[u]=mx[pos[u]] \\ \min\{dis[u],dis[u']\} & \text{otherwise} \end{cases} ans[u]={0min{dis[u],dis[u]}val[u]=mx[pos[u]]otherwise


来算一下时间复杂度,dijkstra 的时间复杂度为 O(mlog⁡n)O(m\log n)O(mlogn),但这道题卡的比较紧,log⁡\loglog 可能会 TLE。

但考虑到本题图中边权只有 000111 两种情况,可以用多源 01bfs 优化,总时间复杂度为 O(m)O(m)O(m)

01bfs 核心是用双端队列,把边权为 000 的放到队首,边权为 111 的放到队尾,这样每次取出队首就一定是当前距离起点距离最小的点之一。本质上是根据 010101 判断省掉了 dijkstra 优先队列排序的 log⁡\loglog

#include <bits/stdc++.h>
using namespace std;
// 省略恶心快读部分
using pii = pair<int, int>;
const int maxn = 2 * 5e5 + 7;  // 分层图两倍空间!int n, m, dis[maxn];           // dis存到每个点的最短路
int pos[maxn], Mx[maxn];       // 每个点所属连通块编号、每个连通块中的最大点权
vector<array<int, 2>> G[maxn]; // 存主图(有向图,分两层)
vector<int> g[maxn];           // 存无向图,用于处理弱连通分量
int ans[maxn];                 // 记录答案struct Node{int val, id; // 点权、编号
}p[maxn];
bool cmp1(Node p1, Node p2){ return p1.val > p2.val; }
bool cmp2(Node p1, Node p2){ return p1.id < p2.id; }void Input(){ // 读入数据read(n, m);for(int i = 1; i <= n; i ++){read(p[i].val); p[i].id = i;G[i].push_back({i+n, 1}), G[i+n].push_back({i, 1}); // 层间转换}for(int u, v, i = 1; i <= m; i ++){read(u, v);G[u].push_back({v, 0}), G[v+n].push_back({u+n, 0}); // 有向图:正图、反图g[u].push_back(v), g[v].push_back(u); // 无向图}
}void getMax(){ // 找到每个弱连通分量中的最大点权int cnt = 0; // 连通块的计数器for(int i = 1; i <= n; i ++){if(pos[i] == 0){ // 没被访问过pos[i] = ++ cnt; Mx[cnt] = max(Mx[cnt], p[i].val); // 更新queue<int> Q; Q.push(i);while(!Q.empty()){int u = Q.front(); Q.pop();pos[u] = cnt; Mx[cnt] = max(Mx[cnt], p[u].val); // 更新for(int v : g[u]){if(pos[v] == 0) Q.push(v);}}}}
}void getPath(){ // 跑最短路 vector<int> vis(maxn);deque<int> Q; memset(dis, 0x3f, sizeof dis); // 初始化为极大值for(int i = 1; i <= n; i ++){ // 所有是最大点权的点都可以作为起点if(p[i].val == Mx[pos[p[i].id]]){Q.push_back(p[i].id); Q.push_back(p[i].id + n); // 把两层都放入dis[p[i].id] = dis[p[i].id + n] = 0; // 起点dis=0}}while(!Q.empty()){ // 01bfsauto u = Q.front(); Q.pop_front();if(vis[u]) continue;vis[u] = true;for(auto [v, w] : G[u]){if(dis[v] > dis[u] + w){dis[v] = dis[u] + w;if(w == 0) Q.push_front(v); // 边权为0的放前面,边权为1的放后面,时间复杂度O(m)(省去dijkstra的排序)else Q.push_back(v);}}}
}void Output(){ // 输出sort(p + 1, p + n + 1, cmp2); // 再按照原来的id排序回去,下面输出for(int i = 1; i <= n; i ++){int ans = min(dis[i], dis[i + n]) + 1; // 初始答案,别忘了+1if(p[i].val == Mx[pos[i]]) ans = 0; // 特判:如果是最大点权那么答案为0cout << ans << " \n"[i == n];}
}signed main()
{ios :: sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);Input();   // 读入getMax();  // 找到每个弱连通分量中的最大点权getPath(); // 跑最短路Output();  // 输出return 0;
}

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

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

相关文章

区块链+隐私计算护航“东数西算”数据安全报告

一、背景与政策支持1.1 "东数西算"工程概况战略定位&#xff1a;作为数字经济时代的核心"底座"&#xff0c;"东数西算"工程是国家级算力资源跨域调配战略工程&#xff0c;旨在构建全国一体化算力网络体系。启动时间与布局&#xff1a;2022年2月&…

STM32——PWR

一、PWR1.1PWR简介PWR&#xff08;Power Control&#xff09;电源控制PWR负责管理STM32内部的电源供电部分&#xff0c;可以实现可编程电压监测器和低功耗模式的功能可编程电压监测器&#xff08;PVD&#xff09;可以监控VDD电源电压&#xff0c;当VDD下降到PVD阀值以下或上升到…

Linux系统网络管理学习.2

目录 一、学习目标与适用场景 二、网络管理基础概念 1. NetworkManager服务 2. 核心管理工具 三、NetworkManager服务管理&#xff08;基础操作&#xff09; 1. 服务状态控制 四、网络参数配置&#xff08;IP/DNS/网关&#xff09; 1. 图形化配置&#xff08;仅了解&…

响应式编程之Flow框架

文章目录一、技术背景与产生原因1.1 响应式编程的兴起1.2 响应式流规范&#xff08;Reactive Streams&#xff09;1.3 解决的问题1.4 响应式编程二、Flow API核心组件2.1 核心概念2.2 接口关系图2.2 接口详解2.3 背压机制三、完整示例3.1 入门示例3.2 基础发布-订阅示例3.3 带背…

ABeam中国 | 中国汽车市场(5)——软件定义汽车(SDV)的智能化应用场景

前言本系列前四篇深入探讨了中国新能源汽车市场的崛起与电动化进程中的挑战。本文聚焦软件定义汽车&#xff08;SDV&#xff09;的三大核心应用场景 ——高级驾驶辅助系统&#xff08;ADAS&#xff09;、智能驾驶舱人机界面&#xff08;HMI&#xff09;及出行即服务&#xff08…

BugKu Web渗透之成绩查询

打开网页&#xff0c;页面如下&#xff1a;输入框中输入不同的数字可以查询不同的结果。输入1后点击submit按钮&#xff0c;下方出现成绩结果。从题目上看感觉是一个SQL注入的漏洞。思路有下&#xff1a;1.自己手动拼接一些常见的SQL注入。2.用bp抓包后用SQLMap去跑。首先&…

【MES】工业4.0智能制造数字化工厂(数字车间、MES、ERP)解决方案:智能工厂体系架构、系统集成以及智能设计、生产、管理、仓储物流等

工业4.0智能制造数字化工厂的解决方案&#xff0c;涵盖了智能制造的背景、企业实现智能工厂的好处、智能工厂的规划与实现方法以及系统实施模块的详细介绍。通过上汽通用凯迪拉克工厂的案例展示了智能工厂的强大能力&#xff0c;强调了数据、技术、管理、人员等关键要素在智能制…

3.【鸿蒙应用开发实战: 从入门到精通】开发入门 Hello World

1.【鸿蒙应用开发实战: 从入门到精通】开发入门 Hello World1.1 前言1.2 创建一个新项目1.2.1 打开DevEco Studio1.2.2 点击 Create Project 创建项目1.3 遗留问题1.4 总结与开发建议1.5 结束语1.1 前言 上篇博文【2.【鸿蒙应用开发实战: 从入门到精通】开发环境搭建】我们已经…

mac系统本地部署Dify步骤梳理

更换终端&#xff0c;适配步骤梳理见笔记前提&#xff1a;已安装docker desktop&#xff0c;若未安装&#xff0c;跳转至文末先安装1.Git软件准备&#xff08;1&#xff09;确认查询Git版本&#xff08;2&#xff09;如果查询不到系统会提示安装&#xff0c;点击安装即可&#…

深度学习——基于卷积神经网络实现食物图像分类【1】(datalodar处理方法)

1. 项目概述 在这个项目中&#xff0c;我们将使用PyTorch框架构建一个卷积神经网络(CNN)来实现食物图像分类任务。我们的数据集包含20种不同的食物类别&#xff0c;包括八宝粥、巴旦木、白萝卜、板栗等常见食物。本文将详细介绍从数据准备、模型构建到训练和评估的完整流程。 …

华中科大联手小米推出ReCogDrive:自动驾驶迎来“认知革命”!

1.【前言】 在开放道路中实现安全、平稳、泛化的自动驾驶&#xff0c;是智能交通领域的“圣杯”。尽管近年来 端到端自动驾驶&#xff08;End-to-End Autonomous Driving, E2E-AD&#xff09; 框架&#xff08;如 UniAD、VAD&#xff09;在 NuScenes 等基准中展现出优异表现&a…

基于 Spring AMQP 的 RabbitMQ 分布式消息系统实战

在分布式系统中&#xff0c;服务间的解耦与异步通信是关键挑战。RabbitMQ 作为一款成熟的消息中间件&#xff0c;凭借其灵活的交换器模型&#xff08;Direct/Fanout/Topic&#xff09;、可靠的消息传递机制&#xff08;持久化、确认机制&#xff09;和丰富的客户端支持&#xf…

计算机网络:天气预报

一、预期结果程序运行输入所要查询的地点&#xff0c;然后出现三个选项实时天气、未来天气、生活指数。二、实现思路&#xff08;一&#xff09;Ubuntu中利用NOWapi服务器获取访问数据api地址&#xff0c;然后创建客户端利用TCP、IPV4协议分别访问实时天气&#xff0c;未来天气…

GD32VW553-IOT OLED移植

1.前言 本来想用他自身的硬件I2C实现的&#xff0c;但是不知道为啥跑demo一点波形都没有&#xff0c;改成推挽也没有波形&#xff0c;只有初始化的电平变化&#xff0c;而且I2C的驱动库好像有点复杂&#xff0c;起始信号结束信号都得单独发的&#xff0c;没有一个全部封装好的库…

刀客doc:Instagram会成为Meta广告业务的第二曲线吗?

文/刀客doc(头条深一度精选作者)一如果现在还用“Facebook的小弟”来定义Instagram&#xff0c;多少显得有些过时了。在和一些出海品牌负责人聊天时&#xff0c;我有个很明显的感受&#xff1a;他们已经不会再把Instagram当成“附属资源”去看待。到2025年第二季度&#xff0c;…

Python日期计算完全指南:从上周五到任意日期的高效计算

引言&#xff1a;日期计算的核心价值在业务系统开发中&#xff0c;日期计算是高频且关键的需求。根据2024年企业系统调查报告&#xff1a;85%的财务系统需要计算上周五&#xff08;工资结算日&#xff09;78%的报表系统依赖周数据统计92%的供应链系统使用工作日计算65%的BI工具…

达梦数据库-重做日志文件(一)

达梦数据库-重做日志文件(redo)(一) 1.查看redo文件 SQL> select * from v$rlogfile;行号 GROUP_ID FILE_ID PATH CLIENT_PATH CREATE_TIME RLOG_SIZE MIN_EXEC_VER MIN_DCT_VER ---------- ----------…

STM32CubeMX 6.15.0 + CLion

-DCMAKE_TOOLCHAIN_FILE./cmake/gcc-arm-none-eabi.cmake 参考 Clion进行嵌入式开发生成.hex文件教程_clion hex-CSDN博客

redis添加超时设置

redis添加参数的超时设置, 并且需要加锁,一开始是用redisTemplate.opsForValue().setIfAbsent("key","value",1,TimeUnit.SECONDS);结果发现这种方式直接会返回空指针错误所以只能对方法加锁来解决加锁和超时的问题import lombok.extern.slf4j.Slf4j; impo…

七牛云实践:我们如何用 AIGC 将产品开发从“人想图”变为“图选图”

在火热进行中的2025深圳国际文创展上&#xff0c;AI玩具、数字艺术等新兴品类无疑成为了焦点。表面的喧嚣之下&#xff0c;一个更深层次的变革正在悄然发生&#xff1a;驱动这些创新产品诞生的底层工作流&#xff0c;正在被AIGC技术深刻影响。 对于身处其中的产品经理、设计师和…