Hdu 6184 三元环计数

版权声明:By MrBird https://blog.csdn.net/MrBird_to_fly/article/details/82777428

题目描述
给一个2e5点2e5边的无向图,求子图 { V=(A,B,C,D) E=(AB,BC,CD,DA,AC) } 的数量。
HINT
考虑把所有边定向,从度数小的点往度数大的点连,这样每个点的出度都小于sqrt(2e5)。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=200007;
int n,m;
int x[maxn],y[maxn],d[maxn];
vector<pair<int,int> >g[maxn];
int cnt[maxn],vis[maxn],id[maxn];
int main(){
	while(~scanf("%d%d",&n,&m)){
		for(int i=1;i<=n;i++)d[i]=0;
		for(int i=1;i<=n;i++)g[i].clear();
		for(int i=1;i<=m;i++)cnt[i]=vis[i]=0;
		for(int i=1;i<=m;i++){
			scanf("%d%d",&x[i],&y[i]);
			d[x[i]]++;
			d[y[i]]++;
		}
		for(int i=1;i<=m;i++){
			if(d[x[i]]<d[y[i]]||(d[x[i]]==d[y[i]]&&x[i]<y[i])){
				g[x[i]].push_back(make_pair(y[i],i));
			}
			else {
				g[y[i]].push_back(make_pair(x[i],i));
			}
		}
		ll ans=0;
		for(int i=1;i<=m;i++){
			int u=x[i],v=y[i];
			for(int j=0;j<g[u].size();j++){
				vis[g[u][j].first]=i;
				id[g[u][j].first]=g[u][j].second;
			}
			for(int j=0;j<g[v].size();j++){
				if(vis[g[v][j].first]==i){
					cnt[i]++;
					cnt[id[g[v][j].first]]++;
					cnt[g[v][j].second]++;
				}
			}
		}
		for(int i=1;i<=m;i++){
			ans+=1ll*cnt[i]*(cnt[i]-1)/2;
		}
		printf("%lld\n",ans);
	}
}

猜你喜欢

转载自blog.csdn.net/MrBird_to_fly/article/details/82777428