版权声明: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);
}
}