无向图三元环计数

小知识点,但不可不学。

定义一个优先级:(u<v) 当且仅当 1. (deg[u]<deg[v]) 2. (deg[u]=deg[v])(u<v)
给无向图中每条边定向,从优先级低连向优先级高,从而图变成 DAG。
不重不漏地暴力统计三元环:原图中的三元环在新图中一定是无向图三元环计数,枚举 (u),再枚举 (u) 的出边中的 (v),再对于每一个 (v) 的指向的点 (O(1)) 判断 (w) 是否被 (u) 指向。
时间复杂度 (O(msqrt m)),可以用根号分治证明:

那么考虑对于每一条边 (lang u rightarrow vrang),它对复杂度造成的贡献是 (out_v),因此总复杂度即为 (sum_{i = 1}^m out_{v_i}),其中 (v_i) 是第 (i) 条边指向的点,(out_v) 是点 (v) 的出度。
考虑分情况讨论。

(v) 在原图(无向图)上的度数不大于 (sqrt m) 时,由于新图每个节点的出度不可能小于原图的度数,所以 (out_v = O(sqrt m))
(v) 在原图上的度数大于 (sqrt m) 时,注意到它只能向原图中度数不小于它的点连边,又因为原图中所有的点的度数和为 (O(m)),所以原图中度数大于 (sqrt m) 的点只有 (O(sqrt m)) 个。因此 (v) 的出边只有 (O(sqrt m)) 条,也即 (out_v = O(sqrt m))

因此所有节点的出度均为 (O(sqrt m)),总复杂度 (sum_{i = 1}^m out_{v_i} = O(m sqrt m))
——扶苏's Blog

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,m,ans,u[N],v[N],deg[N],bk[N];
vector<int>G[N];
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++)scanf("%d%d",&u[i],&v[i]),deg[u[i]]++,deg[v[i]]++;
	for(int i=1;i<=m;i++){
		if(deg[u[i]]>deg[v[i]]||deg[u[i]]==deg[v[i]]&&u[i]>v[i])swap(u[i],v[i]);
		G[u[i]].push_back(v[i]);
	}
	for(int x=1;x<=n;x++){
		for(int i=0;i<G[x].size();i++)bk[G[x][i]]=1;
		for(int i=0;i<G[x].size();i++)for(int j=0;j<G[G[x][i]].size();j++)ans+=bk[G[G[x][i]][j]];
		for(int i=0;i<G[x].size();i++)bk[G[x][i]]=0;
	}
	cout<<ans;
}

原文链接: https://www.cnblogs.com/impyl/p/15786305.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    无向图三元环计数

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/184684

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月12日 上午10:46
下一篇 2023年2月12日 上午10:46

相关推荐