如何正确进行三/四元环计数

预处理每个点的度数 \(\deg_u\),然后按照度数将图定向为 DAG,使得如果 \(u\to v\) 则有 \(\deg u\leq \deg v\)

那么有性质:一个点在定向后的图中的出度不超过 \(\sqrt m\)

证明.

假设 \(u\) 的度数 \(\deg_u\leq \sqrt m\),于是它的出度显然不超过度数,即出度 \(\leq \sqrt m\)

否则如果 \(u\) 的度数 \(\deg_u\geq \sqrt m\),于是如果存在边 \(u\to v\)\(v\) 的度数也 \(\geq \sqrt m\),而总出度是 \(m\),于是这种点的个数不超过 \(\sqrt m\)\(\blacksquare\)

对三元环:它在定向后的图当中只有一种情况:

在度数最小的点上统计它的贡献:假设当前点是 \(u\),暴力枚举 \(u\to v\)\(v\to w\),检查是否有 \(u\to w\)

复杂度分析一下不超过 \(\sum_u \deg_u\rm{out}_u=\mathcal O(m\sqrt m)\)

int ans = 0;
for(int i = 1; i <= n; ++i) {
    for(int v : out[i]) vis[v] = 1;
    for(int v : out[i]) for(int w : out[v]) if(vis[w]) ++ans;
    for(int v : out[i]) vis[v] = 0;
}

对四元环,在度数最大的点的对面的点上统计贡献。不难发现最后的情况是这样:

其中双向边表示不确定这条边的情况,额外要求 \(\deg_u\leq \deg_w\)

那我们可以直接枚举所有 \(u\) 的在原图中的边 \(v\),然后枚举 \(v\) 的出边 \(w\),把贡献记在 \(w\) 上,最后暴力统计答案。

复杂度分析一下显然也是 \(\mathcal O(m\sqrt m)\) 的。

注意:这里不能在度数最小的点上统计答案,因为这样的话枚举顺序是先出边再原图边,而每个点的入度是没有保证的,复杂度有问题。

int ans = 0;
for(int i = 1; i <= n; ++i) {
    static int f[maxn];
    for(int v : to[i]) for(int w : out[v]) if(cmp(i, w)) ans += f[w]++;
    for(int v : to[i]) for(int w : out[v]) f[w] = 0;
}
posted @ 2022-04-29 14:59  whx1003  阅读(468)  评论(0编辑  收藏  举报