Luogu P11892 [XRCOI Round 1] C. 草萤有耀终非火 题解 [ 蓝 ] [ 图论建模 ] [ BFS ] [ 行列连边 ] [ 最小斯坦纳树 ]

news/2025/3/20 0:05:22/文章来源:https://www.cnblogs.com/zhr0102/p/18782185

草萤有耀终非火:蒟蒻的第一个公开赛题,感觉出的有点板了。

Subtask 1

枚举哪些灯被点亮,暴力搜索和模拟即可。

Subtask 2

因为这两个点本来就存在燃料,所以直接将这两盏灯点亮即可,输出 \(2\)

注意特判 \(m=1\) 的情况,此时 \((1,1)\)\((1,m)\) 是同一个点,所以只点亮一盏即可,输出 \(1\)

Subtask 3

因为没有灯在同一行同一列,所以一定点亮不了其他灯,无解,输出 \(-1\) 即可。

同样注意特判 \(m=1\) 的情况,此时若存在灯 \((1,1)\) 则输出 \(1\) 即可。

Subtask 4

考虑同一列全部都有燃料意味着什么。观察发现,如果一行内有两列的灯同时被点亮,那么这两列在其他行的点亮情况一定相同。

这就启发了我们从行与列的角度去考虑问题,这一点同样可以从前两个部分分中得出,行与列是本题的一个关键点。

于是我们继续观察,可以发现,如果将整行和整列都抽象为图论中的节点,就很容易能够刻画他们之间的关系。则一个格点其实就充当了这个图中的无向边。例如,\((a,b),(a,c),(d,b)\) 全部被点亮,就相当于连了 \(a\leftrightarrow b,a\leftrightarrow c ,d\leftrightarrow b\) 的无向边,那么此时 \((d,c)\) 和其他三个点在同一个连通块里,就也会被点亮了。

由此通过中间的满列将旁边两列连接即可求出答案。

Subtask 5

连边之后,我们发现将 \((1,1)\)\((1,m)\) 点亮,就相当于让第 \(1\) 行、第 \(1\) 列和第 \(m\) 列的节点处在一个连通块中。问题就变成加上最少的边,使得这三个点在同一连通块里,即求出他们的最小斯坦纳树。

但这个最小斯坦纳树有点特殊,它的边权是 \(1\),并且只要使 \(3\) 个点连通,于是观察树的形态,发现树是一个从中转点向外发散的形态(即中转点到其他三个节点路径只有一个交点)。关于树的形态的证明具体参考:P6192 【模板】最小斯坦纳树。因此有一个暴力做法。

枚举中转点的位置,以该点为起点 BFS 一遍,最后求出该点到那三个点的最短距离之和即可。正确性显然,因为我们最终一定会找到一个点 \(s\),使得 \(s\) 到另外三个点的最短路不相交,而对于相交的路径一定比 \(s\) 的答案大。

时间复杂度 \(O(t(n+m)^2)\)

Subtask 6

因为是无向图,所以我们反过来考虑也是一样的,以那三个点为起点做 BFS,然后枚举中转点,在中转点处统计三个点到该点的距离之和,取最小值即可。

直接跑最小斯坦纳树也可以,但是没必要。

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

代码

#include <bits/stdc++.h>
using namespace std;
int n,m,s,d[5][200005],ans;
vector<int>g[200005];
queue<int>q;
void bfs(int x,int y)
{bitset<200005>vis;q.push(x);vis[x]=1;d[y][x]=0;while(!q.empty()){int u=q.front();q.pop();for(auto v:g[u]){if(vis[v]==0){vis[v]=1;d[y][v]=d[y][u]+1;q.push(v);}}}
}
void solve()
{cin>>n>>m>>s;for(int i=1;i<=n+m;i++){g[i].clear();d[1][i]=d[2][i]=d[3][i]=1e8;}ans=1e8;while(s--){int u,v;cin>>u>>v;v+=n;g[u].push_back(v);g[v].push_back(u);}bfs(1,1);bfs(n+1,2);bfs(n+m,3);for(int i=1;i<=n+m;i++)ans=min(ans,d[1][i]+d[2][i]+d[3][i]);if(ans<1e8)cout<<ans<<'\n';else cout<<-1<<'\n';
}
int main()
{ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);int t;cin>>t;while(t--)solve();return 0;
}

总结

这题就是一个很典的行列连边,然后跑一个三点最小斯坦纳树就好了。题面还被尺姐锐评写得烂了,而且比赛前几天我整个晚上都盯着题面看修了十多个锅才让这题变得不那么烂。。。

我的某个学长用了一个很神秘的图论建模,然后还要求两点确定,另一点未知的最小斯坦纳树,感觉它的这个做法过于牛了。好像是先从固定的两点跑 BFS,然后建一个虚拟原点,连虚拟原点要每个节点的边,权值就是这个点到另外两个点的距离之和。本质和我那个差不多,但是复杂了一点。然后这玩意本来是要跑 dij 的,但是又观察到权值的值域比较小,就可以用桶排序代替 dij 的优先队列做到线性。这个做法过于牛逼了,膜拜省队爷/bx/bx/bx。

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

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

相关文章

drm study

学习过程 0319:对于任何驱动来说,buffer是最重要的,知道了buffer的创建使用这个驱动就会一半了;现在感觉是一个无头苍蝇,感觉非常复杂:数据结构非常多,之间的关系也非常复杂;不过没关系,先研究buffer通路;可以看见应用层对mmap写入的hello world,驱动中vkms_obj->…

pcie 简介及引脚定义

随着现代处理器技术的发展,在互连领域中,使用高速差分总线替代并行总线是大势所趋。与单端并行信号相比,高速差分信号可以使用更高的时钟频率,从而使用更少的信号线,完成之前需要许多单端并行数据信号才能达到的总线带宽。 PCI总线使用并行总线结构,在同一条总线上的所有…

C++ 基础(1)

0x01 第一个C++程序 #include <iostream>int main() {std::cout << "Hello World!\n"; } // std::cout 向控制台输出内容的指令 // << 输出的运算符 // "" 字符串内容的边界符 // \n 输出换行 // Hello World 输出字符…

在ubuntu系统下与开发板连接问题记录

对我所遇到的问题以及解决方法进行简单的记录在开发板与ubuntu(非虚拟机)连接之后使用lsmod查看是否连接lsusb 我的显示如下:如果可以看到自己的USB设备 那么就说明你已经安装了驱动 如果没有 请安装你的串口对应的驱动 我的驱动是CH340 没有安装的朋友可以去下面网站进行…

maven为什么发生依赖冲突?怎么解决依赖冲突?

maven为什么发生依赖冲突?怎么解决依赖冲突? 我们在开发的时候,偶尔会遇到依赖冲突的时候,一般都是NoClassDefFoundError、ClassNotFoundException、NoSuchMethodError。打开搜索框又发现有这个类,明明就是引入进来了,就是找不到,让人头疼 1. 依赖冲突场景 在maven中依赖…

unstructured

unstructured 是一个开源的 Python 库,专门用于处理非结构化数据,如从 PDF、Word 文档、HTML 文件等中提取文本内容,并将其转换为结构化格式(1)安装依赖库pip install unstructured使用textfrom unstructured.partition.auto import partitionfilename = "a.txt"…

idea如何激活到2099年

前言 最近发现idea如何激活使用的问题、 网络上各种都是骗关注加各种公众号的最后也没有解决问题,下面分享一下我的激活方法是如何激活到2099年。目前适用于idea的所有版本。我以最新的ideaIU-2024.3为例。 一去官网上下载idea 官网下载地址:https://www.jetbrains.com.cn/id…

202108032324 - kafka的生产流程

由上图可以看出:KafkaProducer有两个基本线程: 主线程: 负责消息创建,拦截器,序列化器,分区器等操作,并将消息追加到消息收集器 RecoderAccumulator中; 消息收集器RecoderAccumulator为每个分区都维护了一个Deque<ProducerBatch> 类型的双端队列。 ProducerBatch…

Cython二进制逆向系列(三)运算符

在这篇文章里,我们会讨论Cython是如何处理运算符的(数学运算符、位运算符、in/not in 运算符、 ==运算符与逻辑运算符)。总的来叔其中大部分是调用虚拟机api来实现的。Cython二进制逆向系列(三)运算符在开始前,先给出本文用到的py源代码 def test1(x, y):# 数学运算符a…

QOJ 9785 Shrooks

曼哈顿距离转切比雪夫距离,对限制的贪心满足,扩宽限制,简化信息首先考虑限制的形式:对于两点 \((x_1, y_1), (x_2, y_2)\),要求 \(|x_1 - x_2| + |y_1 - y_2| \le n\)。 但是这个式子与 \(x_1, x_2, y_1, y_2\) 这 \(4\) 个值都强相关,且这里的绝对值也并不好拆开处理。 …

golang的GC机制

一、垃圾回收 什么是垃圾回收?垃圾回收(GC,garbage collection)是自动内存管理的一种形式,通常由垃圾收集器收集并适时回收或重用不再被对象占用的内存,比如众所周知的Java语言就能很好的支持GC。后起之秀——Go语言也同样支持垃圾回收,它使得Go程序员在编写程序的时候不…

fastjson漏洞复现(fastjson 1.2.47)

原理: Fastjson 的 @type 字段允许反序列化时动态指定类,攻击者可以通过指定带有危险行为的类,并结合 RMI/LDAP 远程加载恶意类,从而实现命令执行。开启vulhub靶场//如何验证是否存在fastjson反序列化漏洞 有json数据传输的地方可能存在 可以尝试使用dnslog带外但是不知道…