求无向图的三元环个数

问题描述:

给定nnn个点,mmm条边的无向图,求三元环个数。
n≤100000,m≤min(200000,n∗(n−1)/2)n\le100000,m\le min(200000,n*(n-1)/2)n100000mmin(200000,n(n1)/2)

问题分析:

搜集到的比较好的解法主要有两种:

法一: 把边定向后枚举一条边

先按照原图的边求出每个点的度数,然后把原图的无向边改为有向边:度数小的向度数大的连边,度数相同由编号小的向编号大的连边。(其实按照度数排序就可以了,我们记uuu排序之后的顺序为rnkurnk_urnku

如果你是把边改成了有向边,那么可以保证现在每个点的出度≤m\le\sqrt mm,然后枚举一条边(u,v),然后遍历其中一个端点的邻接点打上标记,再遍历另一个端点的邻接点,遇上标记就ans++。复杂度O(mm)O(m\sqrt m)O(mm)

如果你是按照度数排序,那么枚举一条边(u,v)(rnku&lt;rnkvrnk_u&lt;rnk_vrnku<rnkv),遍历u的邻接点w (rnkw&gt;rnkurnk_w&gt;rnk_urnkw>rnku),如果v与w联通,ans++。当u的度数≥m\ge\sqrt mm时,w的个数≤m\le\sqrt mm。故复杂度也是O(mm)O(m\sqrt m)O(mm)的。

如果懒得把边定向,也可以直接枚举原图边,用hash表记录邻接情况(譬如边(a,b)表示成an+b和bn+a),再枚举边的度数小的端点,判断是否与另一个端点联通,每个环算了三遍,答案最后需要除以3。均摊复杂度似乎仍然是O(mm)O(m\sqrt m)O(mm),但也许会慢一些。

法二:把点按度数分类

从1~n枚举每个点x,把x的邻接点y按度数分类,并打上标记:

  • y的度数≤m\le\sqrt mm,直接枚举y的邻接点z,如果z被标记过,ans++。
    由于总共只会枚举m条xy边,所以这部分的总复杂度是O(mm)O(m\sqrt m)O(mm)的。
  • y的度数&gt;m&gt;\sqrt m>m,继续枚举x的邻接点z,如果y和z相连,ans++。
    由于这样的y的个数≤m\le\sqrt mm个,所以枚举y的复杂度为O(m)O(m)O(m),枚举z的复杂度为均摊O(m)O(\sqrt m)O(m),总复杂度似乎也是O(mm)O(m\sqrt m)O(mm)。(至于枚举z的复杂度的严格证明。。感性理解

这个方法答案也要除以3。

Code:
咕掉了。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值