Loading

4.1 CW 模拟赛 T4. 最小环

前言

这个题会有两种 \(80 \textrm{pts}\) 的做法, 我会一同分析, \(100\) 先暂时放一放

一种方法, 这个先不讲, 这个方法可以做到 \(\mathcal{O} (n^2m + n^3)\), 但是这个不好玩

思路

首先考虑平均环长和需要什么: 环长 \(\&\) 环的边数
如果你在学习矩阵的时候了解过, 你会发现以下内容

关于两点间只经过 n 条边的最短路径长度

用邻接矩阵 M\mathbf{M} 表示一个图, M(i,j)\mathbf{M}(i, j) 是其第 ii 行第 jj 列元素, 表示点 ii 和点 jj 的直接关系,

  • 若点 ii 和点 jj 直接相连, 令 M[i,j]\mathbf{M}[i,j] 等于边 {i,j}\{i, j\} 的权值, 否则等于 \infty
  • i=ji = j 时, 令 M[i,i]=\mathbf{M}[i,i] = \infty

定义矩阵的广义乘法 M×M=mink=1N[M(i,k)+M(k,j)]\mathbf{M} \times \mathbf{M} = \min_{k=1}^{N}[\mathbf{M}(i, k) + \mathbf{M}(k, j)], 也就是把普通的矩阵乘法从求和改成了取最小值, 把内部项相乘改成了相加。

注意

\oplus 运算满足交换律, \otimes 运算满足交换律、结合律,且 \oplus\otimes 存在分配律时, 矩阵乘法具有结合律

当前

  • \oplus 运算 min\min 满足交换律;
  • \otimes 运算 ++ 满足交换律、结合律;
  • \oplus\otimes 存在分配律时 ((min{α1,α1,,αk}+β=min{α1+β,α2+β,,αk+β}\min\{\alpha_1, \alpha_1, \cdots, \alpha_k\} + \beta = \min\{\alpha_1 + \beta, \alpha_2 + \beta, \cdots, \alpha_k + \beta\} )), 这个矩阵乘法具有结合律

定理 6.3.26.3.2 计算邻接矩阵的广义幂 G=Mn\mathbf{G} = \mathbf{M}^n, G(i,j)\mathbf{G}(i,j) 的值是从 iijj 经过 nn 条边(或 n1n-1 个点)的最短路径长度。

证明
n=1n = 1 时, G=M1=M\mathbf{G} = \mathbf{M}^1 = \mathbf{M}, G\mathbf{G} 就是邻接矩阵 M\mathbf{M}, 直接的点之间有一条边, 表示只有经过一条边的路径, 路径的值是两点间的边长;非直接的点的 G\mathbf{G} 值为 \infty, 表示没有只经过一条边的路径。例如, 图 6.2(b)\rm{6.2(b)} 中, 点 11 和点 22M(1,2)=3\mathbf{M}(1,2) = 3, 表示点 11 和点 22 之间只包含一条边的路径, 最短路径是 33M(1,3)=\mathbf{M}(1,3) = \infty, 表示点 11 和点 33 之间只包含一条边的路径有 00 条。

n=2n = 2 时, G=M2=mina=1N[M(i,a)+M(a,j)]\mathbf{G} = \mathbf{M}^2 = \min_{a=1}^{N}[\mathbf{M}(i,a) + \mathbf{M}(a,j)], 只有当 M(i,a)\mathbf{M}(i,a) \neq \inftyM(a,j)\mathbf{M}(a,j) \neq \infty 时, 才有 M(i,a)+M(a,j)\mathbf{M}(i,a) + \mathbf{M}(a,j) \neq \infty, 即如果 iiaaaajj 都有边时, 值为边权之和, 这是一条从 iijj 经过 aa 的路径, 且只经过了 aa 一个点。G(i,j)\mathbf{G}(i,j) 的值等于所有这种路径的最小值, 即所有从 iijj 经过一个中间点(或两条边)的最小路径。例如, 图 6.2(c)\rm{6.2(c)} 中, M(2,2)=2M(2,2) = 2, 表示从点 22 出发回到点 22, 经过两条边的最短路径是 22, 计算过程:M2(2,2)=min(M(2,1)+M(1,2),M(2,2)+M(2,2),M(2,3)+M(3,2),M(2,4)+M(4,2))=min(3+3,,1+1,5+5)=2\mathbf{M}^2(2,2) = \min(\mathbf{M}(2,1) + \mathbf{M}(1,2), \mathbf{M}(2,2) + \mathbf{M}(2,2), \mathbf{M}(2,3) + \mathbf{M}(3,2), \mathbf{M}(2,4) + \mathbf{M}(4,2)) = \min(3 + 3, \infty, 1 + 1, 5 + 5) = 2, 33 条路径分别是 2122\to 1\to 2, 2322\to 3\to 2, 2422\to 4\to 2, 最短路径是 2322\to 3\to 2


pEc36mj.png

有了这个方法, 我们可以简单地计算出答案
但是关键问题在于这个题的边是一个指数类型的问题, 如何对上面的方法进行改造

不难发现边长可以用一个大进制数表示, 但是怎么去转移是一个问题
发现每个位置维护字符串类型的问题, 然后同样去做就行了


稍微理一下方便实现
首先跟普通的方法一样, 我们考虑定义一个矩阵 \(\mathbf{M}\), 初始为邻接矩阵

然后我们需要求的答案就是

\[ans = \max_{l = 1}^{n} \dfrac{\mathbf{M}^l (i, i)}{l} \]

考虑其复杂度 \(\mathcal{O} (n^5)\), 显然是不优秀的

考虑为什么这个做法这么差, 但是题解做法遥遥领先, 好像这个做法不太能优化了


发现可能的原因是这个图比较稀疏?


发现什么原因都不是, 这个做法本质上就是 \(\mathcal{O} (n^5)\) 的, 但是比较 \(\min\) 的时候卡不满, 于是做到了接近 \(\mathcal{O} (n^4)\) 的复杂度, 就可以过了


最后问题是怎么去做最终的比较, 给出一份代码供参考

代码
int len = 0, len1 = 0;
for (int i = 0; i < n; i++) {
    len += Val[i], len1 += rhs.Val[i];
}
double pre = 0;
for (int i = n - 1; i >= 0; i--) {
    pre *= 998244353;
    pre += (double)Val[i] / len;
    pre -= (double)rhs.Val[i] / len1;
    if (pre >= 1e9) return false;
    if (pre <= -1e9) return true;
}
return pre < 0;

当然也可以通分, 反正这样那样的

\(\textrm{Thanks for }\)\(\textrm{the author}\)\(\textrm{ of the idea.}\)

posted @ 2025-04-07 11:08  Yorg  阅读(22)  评论(0)    收藏  举报