「赛前备战」NOIp2020-提高 图论训练

99封情书 提交于 2020-08-06 13:01:53

博主太菜,可能会炸联赛,于是恶补一下 QAQ

题目比较基础,动态更新

Tags

生成树最短路差分约束树的直径与重心LCA树链剖分拓扑序强连通分量 割点 点双连通分量边双连通分量2-SAT二分图正/负环最小环数据结构优化建图

Content

  • 「Codeforces 888G」Xor-MST 生成树
  • 「AtCoder JSC2019 Qual E」Card Collector 生成树
  • 「HDU 4725」The Shortest Path in Nya Graph 最短路
  • 「2018-2019 XIX Open Cup, Grand Prix of Korea」Dev, Please Add This! 2-SAT
  • 「2015 ACM Amman Collegiate Programming Contest」Bridges 边双连通分量 树的直径与重心
  • 「HDU 4370」0 or 1 最短路 最小环

「Codeforces 888G」Xor-MST

update - 2020.8.4

此题需要用到一个叫 Borůvka 的最小生成树算法,大致就是对现在的每一个连通块都找一遍的最短边,最后每个连通块择优,将这些边全部连上。这样复杂度之正确的原因可以参考启发式合并,\(O(|E|\log |V|)\)

对于此题,我们以可以用这样的思路来“择优合并”,即选取两个结点 \(u, v\),使得 \(a_u \oplus a_v\) 最小,然后合并。现在如何找到这个最小的就是个问题。

对于两个二进制数 \(x = (10001010)_2,y = (10000110)_2\),前 \(4\) 位相同,即 \(\text{lcp} = 4\),那么异或一次前四位都是 \(0\)。我们优先考虑二进制下 \(\text{lcp}\) 较大的。

和前缀有关,于是可以断定是 01-Trie。转化到树上,lcp 就成了两个叶子的 LCA,那么我们就该优先考虑 LCA 深度较深的。

遍历整颗 Trie,找到这些 LCA,然后对于一个 LCA,枚举左儿子值域中的所有数 \(a_i\),然后在右子树中查询,并使路径上的 0/1 值尽量和 \(a_i\) 一样以达到异或后最小化的目的。最后这些查询的最小值的和即为所求。

时间复杂度 \(O(n\log n\log a)\)

「AtCoder JSC2019 Qual E」Card Collector

update - 2020.8.4

如果把每一行、列都视作一个点,把卡片视为边,我们会得到一个 \(w+h\) 个点, \(n\) 条边的图。若有一张第 \(i\) 行第 \(j\) 列的卡片,那么就视作一条结点 \(i\)\(h+j\) 之间的边,权值为卡片数值。

考虑题面上取卡片的过程如何转换到图上:我们假定图有向,那么在第 \(i\) 行取走第 \(j\) 列的卡片,就相当于一条 \(i\to j+h\) 的边;同理,在第 \(i\) 列取走第 \(j\) 行的卡片,就相当于一条 \(i + h\to j\) 的边。

试着研究最后取完建出的新图的性质。一个结点的出度最多为 \(1\),那么整个新图就是(内向)基环树的森林。最后将边转为无向。

题目要求权值最大化,那么就是求图上的最大生成基环树森林。要求最大生成基环树森林,可以仿照 Kruskal 算法贪心地取边,与一般 MST 的不同之处就是需要判环,实现要点是一个点所在连通块中最多一个环。

时间复杂度 \(O(n\log n)\)

Code : https://strncmp.blog.luogu.org/solution-at5168

「HDU 4725」The Shortest Path in Nya Graph

update - 2020.8.4

繁琐的最短路题,重点在与怎么建图。

不能直接在层之间的点暴力连边,边数显然可以被卡到 \(O(n^2)\)

我们可以构造 \(2n\) 个虚拟结点,编号在 \([n+1, 2n]\) 的结点为入点,入点 \(n+l\) 引出边连向 \(l\) 层的所有结点;编号在 \([2n+1, 3n]\) 的结点为出点,出点 \(2n+l\) 接受 \(l\) 层所有点向此的连边。

然后对于所有的层 \(l\in[1, n)\),有连边 $2n+l\to n + l + 1 $,\(2n+l+1 \to n+l\)

最后一边 Dijkstra 跑出最短路,时间复杂度(STL 二叉堆) \(O(T(n+m)\log m)\)

「2018-2019 XIX Open Cup, Grand Prix of Korea」Dev, Please Add This!

update - 2020.8.5

物体只能向一个方向运动到底,那么我们可以把极长的一个横块或竖块作为一个整体处理。(类似于一些二分图的题对网格图的处理手段)

预处理出这些块,我们将其视作顶点,显然顶点的规模为 \(O(w\times h)\)

然后根据题意,将题目中的条件转化为图上的信息:若一个块 \(i\) 的端点与另一个块 \(j\) 的中部相交,,单那么顶点 \(i\)\(j\) 连一条单向边向边的原因显然是因为 \(j\) 不能直接到达 \(i\);若一个块 \(i\) 的端点与另一个块 \(j\) 的端点相交,那么那么顶点 \(i\)\(j\) 连一条双向边,可以互相到达。实现时可以用邻接矩阵。

首先我们可以根据原网格以及建好的图得出三个要素:

  • 对于一个 \(\texttt{*}\) 的格子,一定有一个横块或竖块被经过,或者说“被选中”。形式化地讲,设横块、竖块的编号为 \(x, y\),那么一旦不选 \(x\),那必须选 \(y\),反之亦然(\(\neg x\to y,\neg y\to x\))。
  • 起始点所在的两个块都不能(直接或间接)到达某个块 \(i\),那么有 \(x\to \neg x\),因为我们不能选这个块。
  • 对于两个无法互相(直接或间接)到达的点 \(x, y\),我们如果选了 \(x\) 就无法再选 \(y\),反之亦然。形式化地讲,\(x\to \neg y, y\to \neg x\)

然后将这些条件整合,使用 2-SAT,时间复杂度 \(O(w^2\times h^2)\)

「2015 ACM Amman Collegiate Programming Contest」Bridges

update - 2020.8.5

首先在一个 e-BCC(边双联通分量)中加边不会减少桥的数量。那么我们可以先按 e-BCC 缩点,在新图(树)上加边,这样新树上的边都是原图的桥,那么加边就有作用。

那么如何最小化桥数呢?我们可以在树上构造出一个尽量大的环,那么这些环上的边都不再是桥了。

于是找到一段最长的链(直径),在链的两端连边即可达到消除桥的目的。

答案即为 e-BCC 的个数减去缩点所得的树的直径上的点数。

时间复杂度 \(O(Tn)\)

「HDU 4370」0 or 1

update - 2020.8.5

玄妙图论题。

首先题目给定一个矩阵 \(C\),我们把它当作带点之间的边权:第 \(i\) 行第 \(j\) 列的元素 \(C_{i, j}\) 表示边 \(i\to j\) 的边权为 \(C_{i, j}\)。同样的可以把矩阵 \(X\) 作为需要构造的图边的选择情况。

尝试转化题中所给的限制:

  • \(\sum_{i=1}^n X_{1, i}=1\) 表示结点 \(1\) 的出度为 \(1\)
  • \(\sum_{i=1}^n X_{i, n}=1\) 表示结点 \(n\) 的入度为 \(1\)
  • \(\sum_{k=1}^n X_{k, i} = \sum_{j=1}^n X_{i, j}\) 表示对于结点 \(2, 3, \cdots , n-1\),出度等于入度。

最后所求 \(\sum_{1\le i, j\le n} C_{i,j} \times X_{i, j}\) 即为所选边的边权和。

第一种显然的方案是,\(1\)\(n\) 的一条最短路。

第二种是,两个分别经过结点 \(1, n\) 的长度 \(\ge 2\) 的最小环。

接下来就简单了,有两种做法:

  • Floyd。注意这里的最小环和传统的有区别。初始设 \(\text{dist}(i, i) = \infty\),然后正常跑 Floyd 即可。答案即为 \(\max(\text{dist}(1, n), \text{dist}(1, 1)+\text{dist}(n, n))\)。时间复杂度 \(O(Tn^3)\)\(T\) 为数据组数),比较卡。
  • Dijkstra(Spfa)。以 Dijkstra 为例,我们可以在开始时除了起点 \(s\) 外全部赋值 \(\text{dist}(i) = C_{s, i}\),然后正常跑。最后跑三次即可,复杂度 \(O(Tn^2)\)。Spfa 也可以用同样的方式处理。
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!