图论题瞎做
“瞎”指的是我做题看不清细节导致调试时间连续翻倍(迫真
点双连通分量,点双树
洛谷P4606 [SDOI2018]战略游戏
点双树模板题,两点之间的圆点数量就是割断使得两点不连通的点的数量,然后套一个求最小联通块的套路就行了。
洛谷P4630 [APIO2018] Duathlon 铁人两项
考虑枚举两个端点 (s,f) ,判断这两个点之间有多少个合法的点 (c) 满足条件(即存在一条 (s) 到 (f) 的简单路径经过 (c) ),当圆点的权值为 -1 ,方点权值为其代表的点双的点数时,满足条件的 (c) 就恰好是两点路径上的点的权值和,于是问题就变成统计树上所有路径的权值和,简单树形 dp 即可。
OwOJ114526 最少连通块
自己做自己出的题目。
考虑到删除一个点之后的连通块个数就是它在圆方树上面的度数,所以在圆方树上考虑问题,由于和圆点相连的只能是方点,和方点相连的只能是圆点,所以圆点度数和等于方点度数和等于边数,所以方点个数和方点度数和固定,方点度数和为 (sum a_i) ,方点个数为 (1+sum(a_i-1)) ,当方点个数大于圆点个数减一的时候无解,有解时必须满足 (1le 1+sum(a_i-1)le n-1) 。
如果一个方点度数为 (d) ,那么它贡献的最多的边数就是 (d(d-1)/2) ,最少的边数就是 (d-[d=2]) ,注意到度数为 1 的方点并不存在。
当边数最少的时候,我们希望度数为 2 的方点尽可能多,事实上很容易找到一种构造方法使得度数为 2 的方点尽可能多,介绍一下我的构造方法:首先如果所有的 (a_i) 都是 (1) ,显然只有唯一的构造方法就是所有点连到一个方点上面,否则由于 (1le 1+sum(a_i-1)le n-1) ,所以必然存在一个 (a_i=1,a_jge 2) ,然后用一个方点连接 (i) 和 (j) ,删除 (i) ,令 (a_jgets a_j-1) ,此时还是满足有解条件的,然后再循环下去构造。
当边数最大的时候,如果存在一种构造方案使得除一个方点以外所有方点度数都等于 2 ,那么这种构造方式一定是最优的,而用上面的方法构造出来的就是这样一个方案。
AGC038D Unique Path
考虑到如果 (A) 和 (B) 只有一条简单路径, (B) 和 (C) 只有一条简单路径,那么 (A) 和 (C) 必然只有一条简单路径,这个通过圆方树的性质或者分类讨论都可以证明,所以先处理只有一条简单路径的情况,连出一些连通块。
假设处理完后共有 (k) 个连通块,如果要求有多条简单路径的两个点在同一个连通块中显然无解,否则如果 (k e 2) ,我们就存在一种构造方案使得任意两个不在同一个连通块中的点之间的简单路径不止一条,就是一个方点连接所有连通块中的任意一个节点,边数要求最少时就是一个环,要求最多时就是完全图,当然树的情况(没有任何有多条路径的要求)和 (k=2) 的情况要特判。
边双连通分量,边双树
CF51F Caterpillar
操作完最后得到的肯定是一棵有自环的树,那么我们肯定会把边双全部缩成一个点,接下来的问题转化成了树上的了。
如果两个点之间联通但是没有直接连边,那么我们可以不用考虑它们之间合并了,因为合并后会产生新的边双,此时整个边双都要合并,相当于是一路合并过去。
设操作完后得到的图满足条件的路径是 (u o v) ,那么如果将这条路径缩成一个点,那么得到的图就是一张带自环的菊花图,考虑枚举这条路径,问题就变成了如何将一棵树缩成一张菊花图。
首先叶子节点肯定不需要合并,因为这样是不优的,所有除根的非叶子节点肯定都会往上合并,否则所有叶子到根的路径大于 (1) ,所以我们需要的合并次数就是点数减叶子节点个数再减一,这条路径取直径的时候是最优的,所以可以不用再枚举了。
最后如果图不连通还需要一些额外的代价。
CF732F Tourist Reform
首先在一个边双里面的点定向完后肯定是可以相互到达的,直接缩点构建边分树,问题就由图变成了树。
在一棵树上面,如果和点 (u) 相连的所有边中有一条是把 (u) 做为起点,那么 (R_u) 肯定就不是最小值,一棵树边数等于点数减一,所以可以选择留下自身点数最大的点作为答案。
网络流
CF103E Buying Sets
注意一个很重要的性质:任意 (k) 个集合的并的大小都 (ge k) 。
用最大权闭合子图的模型,如果选了某 (k) 个集合,那么选择的元素数量就至少为 (k) ,令元素权值为 (x) ,集合权值额外加上 (-x) ,其中 (x) 很大,那么我们为了最小化权值, (k) 个集合肯定只会选择 (k) 个元素,否则权值就会很大,那么这个方案就会很劣,从而我们不会选择这个方案。
洛谷P4076 [SDOI2016]墙上的句子
生成树
CF888G Xor-MST
考虑使用 Boruvka 构建最小生成树,建立 Trie 树,发现分开的节点恰好有 (n-1) 个,刚好有 (n-1) 条连边,于是直接从每个分开的节点的左边去找其右边异或得到的最小值,然后累计入答案即可,由于 Trie 的树高是严格 (log_2) 的,所以复杂度是正确的,有两个 (log_2) 。
OwOJ114527 最小连通块
再来一波自己做自己出的题目。
考虑使用 kruskal 重构树的思想(不会 kruskal 重构树的可以看这里),建出点分树,那么询问就是找到所有点深度最小的 lca ,然后再倍增跳父亲直到满足要求,唯一需要做的就是维护深度最小的 lca ,直接用 set 维护找 dfs 序最小最大的就可以求 lca 了。
CF1120D Power Tree
将树拍扁成序列,每个节点能够修改的叶子节点对应的就是一个区间,区间加考虑差分后就是两点加或单点加,目的是要让所有点都变成 0 ,相当于是要让所有点的权值都可以一路传递到单点加上面,于是问题就转化成了最小生成树。
最短路
CF241E Flights
估咕谷