三元环计数[根号分治]

#include<bits/stdc++.h>
    
using namespace std;
    
int t;
const int N = 2e5 + 10;
int n,m,ans,pos[N],cnt;
vector<int> g[N];
vector<bitset<N> > h;
    
void solve() {
    cin >> n >> m;
    for(int u,v,i = 1;i <= m;i++) {
        cin >> u >> v;
        g[u].push_back(v);
        g[v].push_back(u);
    }
    const int cp = sqrt(m);
    //非常巧妙的是,这样写非常优美
    //我们只考虑已经遍历过的点,这样每一个三元环就会被考虑3次
    //并且不管当前是不是重点,我都先算出其bitset,如果是重点再存起来,这样很极大增强了代码可读性
    for(int i = 1;i <= n;i++) {
        bitset<N> tmp;
        tmp &= 0;
        for(auto j : g[i]) tmp[j] = 1;
        if(g[i].size() >= cp) h.push_back(tmp),pos[i] = cnt++;
        for(auto j : g[i])
            if(j < i) {
                if(g[j].size() >= cp) ans += (tmp & h[pos[j]]).count();
                else for(auto k : g[j]) ans += tmp[k];
            }
    }
    cout << ans / 3 << '\n';
}
    
signed main() {
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    t = 1;
    while(t--) solve();
    
    return 0;
}
posted @ 2025-04-10 22:38  孤枕  阅读(13)  评论(0)    收藏  举报