更快的无向图三元环计数
updated 2025.11.8
简化了算法流程。
一个一个数是不能突破
设矩阵乘法的复杂度为
例如,使用 Strassen 方法可以将其复杂度降为
算法1. 矩阵乘法
考虑我们枚举一条边
设图的邻接矩阵为
不难看出这是一个矩阵乘法的形式。我们可以求出来
这里需要计算一次矩阵乘法,然后
由于矩阵乘法不会低于
算法 1 的好处在于,不是一个一个数的,可以突破
不过稀疏图上表现很差就是了。
算法2. 生成树
这里是另一个算法。
假设图连通,我们求图的一个 dfs 生成树出来。
(任意生成树都可以,但是 dfs 生成树没有横叉边方便我们处理)
然后将三元环拆成以下四种情况:
- 由三个树边组成。显然不成立。
- 由一个树边两个非树边组成。
- 由两个树边一个非树边组成。
- 由三个非树边组成。
首先看情况 2。
我们枚举一个点
然后判断这些点之间由多少祖先关系即可。
这部分的复杂度为
然后看情况 3。
我们枚举一条非树边
由于没有横叉边,所以只可能是 fa[fa[a]] = b 或者 fa[fa[b]] = a。
最后,将所有树边去掉,然后递归处理上述过程即可。
Q:该算法复杂度?
考虑每次删除一个生成树,每个点的度至少减一。
所以该过程至多进行
复杂度即为
如果阈值分治并结合暴力该算法也可以分析得到
反正也是一个一个数的,不会低于
不过在稀疏随机图上表现会很好。
阈值分治
上述两个算法分别在稠密图和稀疏图上表现良好。
这里使用阈值分治结合一下。
考虑我们先进行
所有点的总度数为
所以两部分的复杂度和为
取
实现
当然,Strassen 方法常数巨大。
所以我实现矩阵乘的时候直接写的压位。复杂度
总复杂度可以平衡到
实测如果跑满
推荐是当剩余点数不超过
261ms
拜谢 UT 提供的复杂度分析指导 orz orz orz