三元环讲解

该博客介绍了如何在无向图中寻找无序三元组(i,j,k),它们之间形成三元环,即每两个点之间都存在边。通过将无向图定向并进行标记,可以实现O(m√m)的时间复杂度来找到所有三元环。代码示例展示了具体的实现过程。
摘要由CSDN通过智能技术生成

参考文章:
不常用的黑科技——「三元环」

引入

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

  1. 有一个连接i,j的边
  2. 有一条连接j,k的边
  3. 有一条链接k,i的边
    即三元环

解决方法:

首先对所有的无向图进行定向,对于任意一条边,从度数大的点连向度数小的点,当度数一样时,从编号小的点连向编号大的点

此时就得到一个有向无环图

然后枚举每一个点,将u所有到达的点v进行标记,标记为u,然后再遍历点v,枚举点v所能到达的点w,如果w存在被u访问的标记,则说明(u,v,w)是一个三元环

证明:

这里讲的很详细,我就不做赘述
不常用的黑科技——「三元环」

复杂度

O ( n + m + n m + m m ) = O ( m m ) O(n+m+n\sqrt{m}+m\sqrt{m})=O(m\sqrt{m}) O(n+m+nm +mm )=O(mm )

代码:

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
vector<int> g[N];
int deg[N], vis[N], n, m, ans;
struct E { int u, v; } e[N * 3];
int main() {
    scanf("%d%d", &n, &m);
    for(int i = 1 ; i <= m ; ++ i) {
        scanf("%d%d", &e[i].u, &e[i].v);
        ++ deg[e[i].u], ++ deg[e[i].v];
    }
    for(int i = 1 ; i <= m ; ++ i) {
        int u = e[i].u, v = e[i].v;
        if(deg[u] < deg[v] || (deg[u] == deg[v] && u > v)) swap(u, v);
        g[u].push_back(v);
    }
    for(int x = 1 ; x <= n ; ++ x) {
        for(auto y: g[x]) vis[y] = x;
        for(auto y: g[x])
            for(auto z: g[y])
                if(vis[z] == x)
                    ++ ans;
    }
    printf("%d\n", ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值