不常用的黑科技——「三元环」

万恶之源:

给定一张无重边、无自环的无向图(点数为$n$,边数为$m$,且$n,m$同阶),问有多少个无序三元组$(i,j,k)$,使得存在:

1. 有一条连接$i,j$的边

2. 有一条连接$j,k$的边

3. 有一条连接$k,i$的边

有一个显然的基于度数的乱搞的做法(本人并没有写过……),可以在这里阅读到:jiachin_zhao [hdu 6184 Counting Stars](三元环计数)

这里介绍一种十分优秀的三元环计数方法:

首先要对所有的无向边进行定向,对于任何一条边,从度数小的点连向度数大的点,如果度数相同,从编号小的点连向编号大的点

此时这张图是一个有向无环图

之后枚举每一个点$u$,然后将$u$的所有相邻的点都标记上“被$u$访问了”,然后再枚举$u$的相邻的点$v$,然后再枚举$v$的相邻的点$w$,如果$w$存在“被$u$访问了”的标记,那么$(u,v,w)$就是一个三元环了

而且每个三元环只会被计算一次

那么现在就只需要证明三件事:

1. 定向后的图是一个有向无环图

如果存在环,那么环上的点度数全部相同,然而度数相同的点是编号较小的连向编号较大的

由于点的编号互不相同,因此环上不会出现$x_1 \lt x_2 \lt x_3 \lt \dots \lt x_n \lt x_1$的情况(其中$x_i$表示环上某个点的编号)

由于这张图有向,而且没有环,因此这张图就是有向无环图

2. 时间复杂度是$O(n \sqrt n)$(在此认为$n,m$同阶)

设$out_u$表示$u$的出边个数,$in_u$表示$u$的入边个数

观察算法流程,会发现对于每一个点$u$,第一次标记所有邻点的时候会对时间复杂度贡献$O(out_u)$

由于是一个有向无环图,因此枚举$v,w$的对时间复杂度的贡献相当于$in_u \times out_u$

既总的时间复杂度为$O(\sum out_u + \sum in_u \times out_u)=O((n+m) + \sum in_u \times out_u)$

又由于是有向无环图,因此所有点的入度之和是$O(n)$的,既$\sum in_u \times out_u \le n \times \max(out_u)$

那么只需要证明$out_u$不会超过$\sqrt m$即可

如果$out_u \gt \sqrt m$,那么它的某个出点$v$,因为是从度数小的往度数大的连边,一定满足$deg_v \gt \sqrt m$

然而$deg_u \times deg_v \gt m$,并没有那么多条边,因此每个点的度数不会超过$\sqrt m$

3. 每个三元环只会被统计一次

三元环在有向无环图上无非就长这样:

也只能且只会在$A$处被计算一次

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 1e5 + 10;
 4 vector<int> g[N];
 5 int deg[N], vis[N], n, m, ans;
 6 struct E { int u, v; } e[N * 3];
 7 int main() {
 8     scanf("%d%d", &n, &m);
 9     for(int i = 1 ; i <= m ; ++ i) {
10         scanf("%d%d", &e[i].u, &e[i].v);
11         ++ deg[e[i].u], ++ deg[e[i].v];
12     }
13     for(int i = 1 ; i <= m ; ++ i) {
14         int u = e[i].u, v = e[i].v;
15         if(deg[u] > deg[v] || (deg[u] == deg[v] && u > v)) swap(u, v);
16         g[u].push_back(v);
17     }
18     for(int x = 1 ; x <= n ; ++ x) {
19         for(auto y: g[x]) vis[y] = x;
20         for(auto y: g[x])
21             for(auto z: g[y])
22                 if(vis[z] == x)
23                     ++ ans;
24     }
25     printf("%d\n", ans);
26 }
一个样例程序

猜你喜欢

转载自www.cnblogs.com/KingSann/p/9590525.html
今日推荐