无向图找三元环模板

方法:暴力
复杂度:O(msqrt(m))
步骤:按点的度数分成两类,分别暴力
①统计每个点的度数
②入度<=sqrt(m)的分为第一类,入度>sqrt(m)的分为第二类
③对于第一类,暴力每个点,然后暴力这个点的任意两条边,再判断这两条边的另一个端点是否连接
因为m条边最多每条边遍历一次,然后暴力的点的入度<=sqrt(m),所以复杂度约为O(msqrt(m))
④对于第二类,直接暴力任意三个点,判断这三个点是否构成环,因为这一类点的个数不会超过sqrt(m)个,
所以复杂度约为O(sqrt(m)^3)=O(msqrt(m))

⑤判断两个点是否连接可以用set,map和Hash都行

const int MAXN = 100050;

set<int> mapp[MAXN];//用set是为了使用find 

bool vis[MAXN];
int Du[MAXN];//统计各点的度 
vector<int> high;
int N,M;//N是点数,M是边数。

int main(){
	
	while(scanf("%d %d",&N,&M)!=EOF){
		memset(Du,0,sizeof Du);
		memset(vis,false,sizeof vis);
		for(int i=1 ; i<=M ; ++i){
			int a,b;
			scanf("%d %d",&a,&b);
			mapp[a].insert(b);
			mapp[b].insert(a);
			Du[a]++;Du[b]++;
		}
		int s = sqrt(M);
		long long sum = 0;
		for(int i=1 ; i<=N ; ++i){
			if(Du[i]<=s){
				vis[i] = true;
				set<int>::iterator it;
				for(it=mapp[i].begin() ; it!=mapp[i].end() ; ++it){
					if(vis[*it])continue;
					set<int>::iterator itt;
					for(itt=it ; itt!=mapp[i].end() ; ++itt){
						if(vis[*itt])continue;
						if(mapp[*it].find(*itt) != mapp[*it].end()){
							++sum;
						}
					}
				}
			}
			else {
				high.push_back(i);
			}
		}
		for(int i=0 ; i<high.size() ; ++i){
			for(int j=i+1 ; j<high.size() ; ++j){
				if(mapp[high[i]].find(high[j]) == mapp[high[i]].end())continue;
				for(int k=j+1 ; k<high.size() ; ++k){
					if(mapp[high[i]].find(high[k])!=mapp[high[i]].end() && mapp[high[j]].find(high[k])!=mapp[high[j]].end())
						++sum;
				}
			}
		}
		for(int i=1 ; i<=N ; ++i)mapp[i].clear();
		high.clear();
	}
	
	return 0;
} 
 

原文地址:https://www.cnblogs.com/vocaloid01/p/9514075.html