【NOI 2018】归程(Kruskal重构树)

题面在这里就不放了。

同步赛在做这个题的时候,心里有点纠结,很容易想到离线的做法,将边和询问一起按水位线排序,模拟水位下降,维护当前的各个联通块中距离$1$最近的距离,每次遇到询问时输出所在联通块的信息。

离线的思路对满分做法有一定的启发性,很容易想到将并查集持久化一下就能支持在线了。

但是这个是两个$log$的,有卡常的风险也不是很方便写。

当时思考了一下就快速写完离线做法就去做其他题了。

对于这道题,有一个更好的做法:Kruskal重构树。

事实上如果你了解这个东西,那你就能很快的给出解,那仅此以这道题作为学习Kruskal重构树的例子。

先给出一个经典的模型:

  • 给定一张无向图,每次询问两点之间所有简单路径中最大边权的最小值。

一个常规的做法就是建出最小生成树,答案就是树上路径的最大边权,正确性显然。

当然也可以用我们要讲的Kruskal重构树来解决,算法虽不同,思想类似。

Kruskal中我们连接两个联通块(子树)时直接用一条边将对应的两个点相连,但在Kruskal重构树中,我们先建一个虚点作为两个子树的树上父亲,让两个联通块分别与该点相连,注意的是要维护并查集合并时的有序性。

我们称新建的虚点为方点,代表了原图中的一条边,原图中的点为圆点,则该树有一些优雅的性质:

  1. 这是一颗二叉树,并且相当于一个堆,因为边是有顺序合并的。
  2. 最小生成树上路径的边权信息转化成了点权信息。

那么回顾刚刚的那个模型,每个询问就相当于回答Kruskal重构树上两点$lca$的权值。

 

最后在回来看这道题,就显得十分轻松了。

我们把每条边按照水位线从高到低依次插入,可以发现每次规定一个水位下限,车子能走的范围对应了Kruskal重构树上的一棵子树,那么每次只要倍增找到最紧的那个限制的点就可以了。

  1 #include <cstdio>
  2 #include <queue>
  3 #include <cstring>
  4 #include <algorithm>
  5 
  6 typedef long long LL;
  7 const int N = 600005, INF = 2e9 + 7, LOG = 21;
  8 
  9 int tc, n, m, Qi, k, s;
 10 int dis[N], flg[N], val[N], mdi[N], gr[LOG][N];
 11 std::priority_queue<std::pair<int, int> > Q;
 12 
 13 inline void Read(int &x) {
 14     x = 0; static char c;
 15     for (c = getchar(); c < '0' || c > '9'; c = getchar());
 16     for (; c >= '0' && c <= '9'; x = (x << 3) + (x << 1) + c - '0', c = getchar());
 17 }
 18 
 19 struct Edge {
 20     int u, v, a;
 21     inline friend bool operator < (Edge a, Edge b) {
 22         return a.a > b.a;
 23     }
 24 } e[N];
 25 
 26 int yun, las[N], to[N << 1], pre[N << 1], wi[N << 1];
 27 inline void Add(int a, int b, int c = 0) {
 28     to[++yun] = b; wi[yun] = c; pre[yun] = las[a]; las[a] = yun;
 29 }
 30 void Gragh_clear() {
 31     memset(gr, 0, sizeof gr);
 32     memset(las, 0, sizeof las);
 33     yun = 0;
 34 }
 35 
 36 namespace DSU {
 37     int fa[N];
 38     void Init() {
 39         for (int i = 1; i <= n + m; ++i) {
 40             fa[i] = i;
 41             if (i <= n) mdi[i] = dis[i], val[i] = -1;
 42         }
 43     }
 44     int Seek(int x) {
 45         return (x == fa[x])? (x) : (fa[x] = Seek(fa[x]));
 46     }
 47     void Merge(int x, int y) {
 48         fa[Seek(y)] = x;
 49     }
 50 }
 51 
 52 void Dij() {
 53     for (int i = 1; i <= n; ++i) {
 54         dis[i] = INF; flg[i] = 0;
 55     }
 56     dis[1] = 0;
 57     Q.push(std::make_pair(0, 1));
 58     for (; !Q.empty(); ) {
 59         int x = Q.top().second; Q.pop();
 60         if (flg[x]) continue;
 61         flg[x] = 1;
 62         for (int i = las[x]; i; i = pre[i]) {
 63             if (dis[to[i]] > dis[x] + wi[i]) {
 64                 dis[to[i]] = dis[x] + wi[i];
 65                 Q.push(std::make_pair(-dis[to[i]], to[i]));
 66             }
 67         }
 68     }
 69 }
 70 
 71 int main() {
 72     freopen("return.in", "r", stdin);
 73     freopen("return.out", "w", stdout);
 74     
 75     scanf("%d", &tc);
 76     for (; tc; --tc) {
 77         scanf("%d%d", &n, &m);
 78         Gragh_clear();
 79         for (int i = 1, x, y, a, l; i <= m; ++i) {
 80             //scanf("%d%d%d%d", &x, &y, &l, &a);
 81             Read(x); Read(y); Read(l); Read(a);
 82             Add(x, y, l); Add(y, x, l);
 83             e[i] = (Edge) { x, y, a };
 84         }
 85         Dij(); DSU::Init();
 86         
 87         std::sort(e + 1, e + 1 + m);
 88         for (int i = 1; i <= m; ++i) {
 89             int x = DSU::Seek(e[i].u), y = DSU::Seek(e[i].v);
 90             if (x == y) continue;
 91             val[i + n] = e[i].a;
 92             mdi[i + n] = std::min(mdi[x], mdi[y]);
 93             DSU::Merge(i + n, x); DSU::Merge(i + n, y);
 94             gr[0][x] = gr[0][y] = i + n;
 95         }
 96         
 97         for (int i = 1; i < LOG; ++i) {
 98             for (int j = 1; j <= n + m; ++j) {
 99                 if (gr[i - 1][j]) gr[i][j] = gr[i - 1][gr[i - 1][j]];
100             }
101         }
102         
103         scanf("%d%d%d", &Qi, &k, &s);
104         for (int x, a, lans = 0; Qi; --Qi) {
105             //scanf("%d%d", &x, &a);
106             Read(x); Read(a);
107             x = (x + (LL) k * lans - 1) % n + 1;
108             a = (a + (LL) k * lans) % (s + 1);
109             for (int i = LOG - 1; ~i; --i) {
110                 if (gr[i][x] && val[gr[i][x]] > a) x = gr[i][x];
111             }
112             printf("%d\n", mdi[x]);
113             lans = mdi[x];
114         }
115     }
116     
117     return 0;
118 }
View Code

 

$\bigodot$技巧&套路:

  • kruskal重构树的构建,最小生成树上最值问题的再探。

转载于:https://www.cnblogs.com/Dance-Of-Faith/p/9333015.html

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

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

相关文章

jdbc连接mysql数据库的常用对象_JDBC常用对象

主要作用:注册驱动 实际开发中使用Class.forName("com.mysql,jdbc.Drive")&#xff1b;这种方式&#xff0c;因为之前的方式会导致注册两次驱动获得连接 Connection getConnection(String url,String username,String password)url写法&#xff1a;jdbc:mysql://loca…

latex大括号 多行公式_如何快速入门 LaTeX,在 XMind 2020 中轻松输入方程。

数学方程输入对于很多理工科朋友来说是一件让人头疼的事情。不仅是数学方程本身就纷繁复杂花样百出&#xff0c;各种输入语法更是劝退无数人。然而很多看似复杂的东西其实并非如想象中的难&#xff0c;抓住本质即可快速入门。今天和大家分享下如何快速入门 LaTeX&#xff0c;在…

全国计算机等级考试题库二级C操作题100套(第08套)

更多干货推荐可以去牛客网看看&#xff0c;他们现在的IT题库内容很丰富&#xff0c;属于国内做的很好的了&#xff0c;而且是课程刷题面经求职讨论区分享&#xff0c;一站式求职学习网站&#xff0c;最最最重要的里面的资源全部免费&#xff01;&#xff01;&#xff01;点击进…

部署及配置Lync Server 2013 监控功能

在上面一篇文章中我们已经部署了存档功能&#xff0c;并且在标准版环境搭建了一台SQLServer服务器作为后端数据库服务器&#xff0c;有了这台服务器我们可以做什么呢&#xff1f;存档&#xff0c;当然还有监控&#xff0c;以及整个CMS。当然这都是一步一步演变的&#xff0c;并…

python处理excel的方法有哪些_python简单处理excel方法

1 # codingutf-8 2 3 import xlrd # 读模块4 import xlwt # 写模块5 6 7 def read_excel():8 """9 读取excel文件方法说明&#xff08;此函数只是对xlrd用法的说明&#xff0c;看看就好。xlrd已经很好用了&#xff09;10 :return:11 """12 # 打开…

mysql 客户服务号获取_《MySQL排错指南》——1.4 获取查询信息-阿里云开发者社区...

本节书摘来自异步社区出版社《MySQL排错指南》一书中的第1章&#xff0c;第1.4节&#xff0c;作者&#xff1a;【美】Sveta Smirnova(斯维特 斯米尔诺娃)&#xff0c;更多章节内容可以访问云栖社区“异步社区”公众号查看。1.4 获取查询信息正如前一节看到的一样&#xff0c;数…

全国计算机等级考试题库二级C操作题100套(第09套)

第09套&#xff1a; 给定程序中,函数fun的功能是将不带头节点的单向链表结点数据域中的数据从小到大排序。即若原链表结点数据域从头至尾的数据为&#xff1a;10、4、2、8、6&#xff0c;排序后链表结点数据域从头至尾的数据为&#xff1a;2、4、6、8、10。 请在程序的下划线处…

基于交换芯片的五元组的PCL规则过滤功能

2019独角兽企业重金招聘Python工程师标准>>> 基于交换芯片的五元组的PCL规则过滤功能作者: 韩大卫吉林师范大学2012.12.10Not Approved by Document Control Review Copy Only基于Marvell 98DX51xx/81xx交换芯片的五元组等的策略规则(PCL)过滤功能.现将部分的功能的…

python生成树状图_python 生成 树状结构

forwarding_recp re.compile(".*?发件人:(.*?);.*?发送时间:.*?收件人:(.*?)主题", re.S)def parse_addr(addr, split_str,): l[]ifaddr:for a inaddr.split(split_str): l.append(utils.parseaddr(a)[1])returnldef gen_forwarding(con): #参数是解析过后的邮…

remove()与empty()的区别

1、empty() - 从被选元素中删除子元素&#xff1b; 2、remove() - 删除被选元素(及其子元素)&#xff1b; 3、remove() 方法也可接受一个参数&#xff0c;允许您对被删元素进行过滤。转载于:https://www.cnblogs.com/hwldyz/p/9335717.html

2013年6月和12月CISA考试报名,认证,CPE维持和备考要点

2013年6月和12月CISA考试报名,认证,CPE维持和备考要点 2013年6月和12月CISA考试报名,认证,CPE维持和备考要点 消息来源&#xff1a;http://www.isaca.org/CERTIFICATION/CISA-CERTIFIED-INFORMATION-SYSTEMS-AUDITOR/REGISTER-FOR-THE-EXAM/Pages/default.aspx在线报名费用 早…

全国计算机等级考试题库二级C操作题100套(第10套)

第10套&#xff1a; 给定程序中&#xff0c;函数fun的功能是&#xff1a;判定形参a所指的NN&#xff08;规定N为奇数&#xff09;的矩阵是否是"幻方"&#xff0c;若是&#xff0c;函数返回值为1&#xff1b; 不是&#xff0c;函数返回值为0。“幻方"的判定条件是…

mysql字节对齐_结构体字节对齐(转)

结构体字节对齐在用sizeof运算符求算某结构体所占空间时&#xff0c;并不是简单地将结构体中所有元素各自占的空间相加&#xff0c;这里涉及到内存字节对齐的问题。从理论上讲&#xff0c;对于任何变量的访问都可以从任何地址开始访问&#xff0c;但是事实上不是如此&#xff0…

python docx 合并文档 图片_不再为处理PDF烦恼,python处理操作PDF全攻略

本篇聊下Python对pdf的各种操作&#xff0c;包含pdf转word&#xff0c;pdf转图片&#xff0c;pdf翻转&#xff0c;加密&#xff0c;加水印等。pdf转换word文档 保留格式pdf转换为word文档&#xff0c;被大众经常使用的是纯Python库pdfminer和python-docx搭配使用&#xff0c;不…

new blog

new blog转载于:https://www.cnblogs.com/uuzlove/p/9336405.html

windows server 2012 初安装体验

昨天晚上的windows server 2012 已时行 了发布了&#xff0c;为之在之前我已进行了下载测试安装&#xff0c;本来晚间想用来在虚拟机下进行安装VM-tool工具的&#xff0c;但是却因种种原因没有成功&#xff0c;为之补一下前面没有安装的过程截图。 进入下载页后&#xff0c;下载…

python 多进程 调用模块内函数_python子进程模块subprocess详解与应用实例 之一

分类&#xff1a; Python/Ruby 2014-09-09 10:59:42 subprocess--子进程管理器 一、subprocess 模块简介 subprocess最早是在2.4版本中引入的。 subprocess模块用来生成子进程&#xff0c;并可以通过管道连接它们的输入/输出/错误&#xff0c;以及获得它们的返回值。 它用来代替…

安卓APP_ 控件(1)—— TextView

摘自&#xff1a;安卓APP_ 控件&#xff08;1&#xff09;—— TextView 作者&#xff1a;丶PURSUING 发布时间&#xff1a; 2021-03-28 21:53:49 网址&#xff1a;https://blog.csdn.net/weixin_44742824/article/details/115283233 本文为学习笔记&#xff0c;是安卓APP学习的…

python udp 大文件_Python:通过UDP发送大对象

我是套接字编程的新手&#xff0c;最近为它挑选了Python。我有几个问题&#xff0c;我似乎无法找到明确的答案。Python&#xff1a;通过UDP发送大对象我正在研究通过UDP发送数据&#xff0c;并写了一个简单的python脚本来做到这一点。可以很好地发送小对象(准确地说是小腌制对象…

Flask入门系列(转载)

一、入门系列&#xff1a; Flask入门系列(一)–Hello World 项目开发中&#xff0c;经常要写一些小系统来辅助&#xff0c;比如监控系统&#xff0c;配置系统等等。用传统的Java写&#xff0c;太笨重了&#xff0c;连PHP都嫌麻烦。一直在寻找一个轻量级的后台框架&#xff0c;学…