最短路
NOI2019 D2T1 弹跳
KD 树
线段树套set -> 线段树套并查集?
POI2014/2015 ???
\(n\) 个点 \(m\) 条边 DAG。求删掉每个点后 \(1\) 到 \(n\) 最短路。
\(n,m\le 3\times 10^5\)。
首先明显要先求 \(f_i\) 表示 \(1\) 到 \(i\) 的最短路,\(g_i\) 表示从 \(i\) 到 \(n\) 的最短路。
先考虑一个一个求解。
发现删掉 \(x\) 后,原来拓扑序小于 \(x\) 的点(称作 \(A\))内部没有任何影响,拓扑序大于 \(x\) 的点(称作 \(B\))内部也没有影响。
那么此时答案就是 \(\min\limits_{u\in A,v\in B,(u,v)\in E}(f_u+g_v+w_{(u,v)})\)。
如何对多个求解呢?发现 \(x\) 加一时,只有两个点有变化,随便动态维护即可。
复杂度是一个 \(\log\)。
Gym 101372 E
\(n\) 点 \(m\) 边有向图,计算每个点传递闭包大小,允许有误差,最多差两倍。
\(n,m\le 2\times 10^5\)。
先缩成一个 DAG,给每个点随机一个权值,然后令 \(f_i\) 表示他能到的所有点的权值最小值。可以反向拓扑求。
然后由于随机 \([1,v]\) 的 \(n\) 个数,最小值的期望是 \(\frac{1+v}{n+1}\),解一解可以知道 \(n\approx \frac{1+v}{f_i}-1\)。
多随机几次取平均即可。
([BJOI2014]想法???)
生成树
SD 省队集训2018 D1T1
\(n\) 个点 \(m\) 条边的无向图,第 \(i\) 条边权值是 \(2^i\),要求经过每条路至少一次,问最小总花费。
\(n,m\le 10^5\)。
首先发现,一条边只会经过 \(1\) 次或 \(2\) 次。(欸?smg?)
先把所有边都跑一遍,变成一条边只会经过 \(0\) 次或 \(1\) 次。同时度数为偶数的点已经不用管了,度数为奇数的点还要多走一次。
把这些奇点拎出来,问题就变成了每条边有权值,选了这条边可以把两个端点异或一,要最小的代价把他们都变成 \(0\)。
由于边权很特殊,让最大的边权最小就好了。
二分最大的边权,判断能不能搞出来。
\(O(m\log m)\)。
经典题
\(n\) 个点 \(m\) 条边的无向图,边是白的或者黑的,问多少棵生成树有恰好 \(k\) 条白边。
把白边看作 \(x\),黑边看作 \(1\),跑一下 Ex-Matrix Tree 即可。
直接算复杂度很高,可以代几个值进去然后拉格朗日插值。
复杂度 \(O(n^4)\)。
Hihocoder Challenge 28
求所有生成树权值和的 \(k\) 次方和
\(n,k\le 50,w\le 10^9\)
把每条边看成多项式 \(\sum\limits_{i=0}^k\frac{w^ix^i}{i!}\)。答案就是行列式乘 \(k!\) 的 \(x^k\) 项系数。
行列式是一个 \(n^2\) 次多项式。(假设 \(n,k\) 同阶)
直接搞是 \(O(n^5)\)。
最小方差生成树
\(n\le 10^5\)
先考虑 \(O(m^3\log m)\) 的做法:
首先若固定一个 \(\overline{w}\),那么把每条边的边权设为 \((w-\overline{w})^2\),求个最小生成树即可。
发现当 \(\overline{w}\) 变大时,最小生成树的形态最多会变 \(m^2\) 次(越过两条边的平均值)。那么枚举这 \(m^2\) 棵树求出其取最小值的 \(\overline{w}\)。
如何优化?
有个结论:一条边在最小生成树出现或者消失一定是在两条边的平均值处,不会在别的地方开始出现或消失。应该很显然。
设第 \(i\) 条边开始出现的 \(\overline{w}\) 为 \(l_i\),开始消失的 \(\overline{w}\) 为 \(r_i\)。那么 \(l_i\) 和 \(r_i\) 一定是某个 \(j\) 的 \(\frac{w_i+w_j}{2}\)。
维护 \(l_i,r_i\) 可以做到 \(O(m\log m)\)。具体的,把所有边按边权排序,从小到大进入 LCT,动态维护最大生成树。每次如果加入之前 \(u_i\) 和 \(v_i\) 不连通,那么 \(l\) 是 \(-\infty\)。否则取出 \(u_i,v_i\) 路径上最小的 \(w_j\),\(l_i\) 和 \(r_j\) 都是 \(\frac{w_i+w_j}{2}\),然后拿 \(i\) 替代 \(j\)。最后还在 LCT 里的边的 \(r\) 都是 \(+\infty\)。
2-SAT
???
\(n\) 点 \(m\) 边无向图,\(k\) 个集合 \(S_1\dots S_k\),满足每个点恰好属于一个集合。
现在要在每个集合中选出恰好一个点,使得每一条边至少一个点被选择。
求方案。
\(n,m,k\le 10^6\)
明显 2-SAT。首先对于每条边,一个点的反点向另一个点的正点连边。
然后对于一个集合恰好选一个点,暴力连边边数就炸了。
稍微优化一下,对于每个集合,\(A_i\) 表示前 \(i\) 个点有没有选出一个,\(B_i\) 表示后 \(n-i+1\) 个点有没有选出一个。
那么集合中第 \(i\) 个点的正点向 \(A_i\) 的正点和 \(B_i\) 的正点连边,\(A_i\) 的反点和 \(B_i\) 的反点向集合中第 \(i\) 个点的反点连边。
\(A_i\) 的正点向 \(A_{i+1}\) 的正点连边,\(A_{i+1}\) 的反点向 \(A_i\) 的反点连边。\(B\) 同理。
\(A_i\) 的正点和 \(B_{i+1}\) 的反点互相连边,\(A_i\) 的反点和 \(B_{i+1}\) 的正点互相连边。
复杂度是线性的。
???
\(n\) 个点 \((x_i,y_i)\),可以在每个点上建建筑,以该点为斜边中心的等腰直角三角形,斜边必须平行于 \(x\) 轴或 \(y\) 轴。可以发现至多能建两个。
所有建筑边长必须一样,问最大边长。
\(n\le 60\)。
首先二分答案。
一个点可能建出的四个建筑,按顺时针编号为 \(1\) 到 \(4\),发现建了 \(1\) 就不可能建 \(2\)(反过来也是),建了 \(3\) 就不可能建 \(4\)(反过来也是)(暂时不用考虑 \(1\) 和 \(4\),\(2\) 和 \(3\),待会会考虑到)
然后大力枚举两栋建筑两边。
跑个 2-SAT 即可。
TCO Hard
\(n\) 个点的树,\(m\) 个物品,你要给每个物品确定一个位置 \(p_i\)。
\(k\) 个限制,形如 \(p_x\) 为根时,\(p_y\) 和 \(p_z\) 的 LCA 是 \(Q\)。
求方案。
\(n,m\le 100,k\le 10^5\)
先随便钦定一个根。
点 \(F_{x,y}\) 表示 \(p[x]\) 是否在以 \(y\) 为根的子树里。
\(F_{x,1}\) 肯定是 \(1\),反点向正点连边。
\(F_{x,p}\) 为 \(1\) 时,\(F_{x,fa[p]}\) 也是 \(1\),连一连。
\(F_{x,son_{u,1}}\) 为 \(1\) 时,\(F_{x,son_{u,i}}(i\ne 1)\) 一定是 \(0\),连一连。
接下来考虑限制。相当于以 \(Q\) 为根时 \(p_x,p_y,p_z\) 在三棵不同子树中。
\(F_{x,Q}\) 为 \(0\) 时,\(F_{y,Q}\) 和 \(F_{z,Q}\) 都是 \(1\),连一连。
\(F_{x,Q}\) 为 \(1\) 时,\(F_{y,Q}\) 和 \(F_{z,Q}\) 都是 \(0\),连一连。
其它同理。
复杂度 \(O(nm+k)\)。
欧拉回路
BEST 定理
昨天说过了,这里不再赘述。
CF547D
\(n\) 个点 \((x_i,y_i)\),对点黑白染色,使得每行每列都满足黑点数和白点数之差不大于 \(1\)。
\(n\le 2\times 10^5\)
对每行和每列都建个图。对每个点,把行和列连起来。这是个二分图。
如果是要求黑点白点数完全相等呢?
实际上就是对每个连通块求个欧拉回路,把从左往右的边看成白的,从右往左的边看成黑的。这就是合法的了。
原题呢?
那么就是度数是偶数的点黑白数要相等(不然至少差 \(2\)),度数是奇数的点黑白差恰好为 \(1\)。
那么左右都建一个虚点,左边的奇点连向右边的虚点,右边的奇点连向左边的虚点,对于每个连通块如果两个虚点都是奇点肯定就不行了,否则求出欧拉回路后把虚边删掉,一定合法。
???
\(n\) 个点 \(m\) 条边无向图,对边集的所有子集(共 \(2^m\) 个),若导出子图的每个连通块内都存在欧拉回路,就把答案加上这个子图的边数的平方。
答案对 \(10^9+7\) 取模。
\(n\le 10^5\)
等价于每个点度数都是偶数。
如果是问方案数怎么算?
首先每个连通块互不干扰。对它求生成树,如果非树边选了,把它连的两个点在树上路径的所有边情况都反转一下,是可以的。方案数就是 \(2^{非树边}=2^{E-V+1}\)。
那如果是 \(E\) 呢?
枚举边,看看有多少个方案包含它。
如果这是个桥边那么如果选了,肯定无法走出欧拉回路。挂了。
否则由于这条边已经被固定选了,删掉这条边后仍然是一个连通块,方案数就是 \(2^{E-V}\)。
如果是 \(E^2\) 呢?
发现就是枚举边对,问多少个方案包含它们。
如果这两条边中有桥,就挂了。
如果它们不在一个连通块,按照一条边的方法分开考虑;
如果它们都是非树边,那么方案数是 \(2^{E-V-1}\)(已经固定了两个);
如果它们其中一个是树边,那么选了之后连通性改变当且仅当非树边包住了树边;
如果它们都是树边,那么选了之后连通性改变当且仅当有至少一条非树边包住了这两条边,而且没有非树边连接这两边中间和这两边外面。
有种神奇的转换方法:
给每条非树边随机权值。然后把每条非树边两点路径上所有树边的权值异或上这条非树边的权值。
那么后面两个就变成了两边权值必须相等。
用个 map 之类的就没了。
时间复杂度 \(O(m\log m)\)。