赞
踩
给定
n
n
n个点,
m
m
m条边的无向图,求三元环个数。
n
≤
100000
,
m
≤
m
i
n
(
200000
,
n
∗
(
n
−
1
)
/
2
)
n\le100000,m\le min(200000,n*(n-1)/2)
n≤100000,m≤min(200000,n∗(n−1)/2)
搜集到的比较好的解法主要有两种:
先按照原图的边求出每个点的度数,然后把原图的无向边改为有向边:度数小的向度数大的连边,度数相同由编号小的向编号大的连边。(其实按照度数排序就可以了,我们记 u u u排序之后的顺序为 r n k u rnk_u rnku)
如果你是把边改成了有向边,那么可以保证现在每个点的出度 ≤ m \le\sqrt m ≤m ,然后枚举一条边(u,v),然后遍历其中一个端点的邻接点打上标记,再遍历另一个端点的邻接点,遇上标记就ans++。复杂度 O ( m m ) O(m\sqrt m) O(mm )。
如果你是按照度数排序,那么枚举一条边(u,v)( r n k u < r n k v rnk_u<rnk_v rnku<rnkv),遍历u的邻接点w ( r n k w > r n k u rnk_w>rnk_u rnkw>rnku),如果v与w联通,ans++。当u的度数 ≥ m \ge\sqrt m ≥m 时,w的个数 ≤ m \le\sqrt m ≤m 。故复杂度也是 O ( m m ) O(m\sqrt m) O(mm )的。
如果懒得把边定向,也可以直接枚举原图边,用hash表记录邻接情况(譬如边(a,b)表示成an+b和bn+a),再枚举边的度数小的端点,判断是否与另一个端点联通,每个环算了三遍,答案最后需要除以3。均摊复杂度似乎仍然是 O ( m m ) O(m\sqrt m) O(mm ),但也许会慢一些。
从1~n枚举每个点x,把x的邻接点y按度数分类,并打上标记:
这个方法答案也要除以3。
Code:
咕掉了。。。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。