1. 程式人生 > >Hdu 6184 三元環計數

Hdu 6184 三元環計數

題目描述 給一個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);
	}
}