# Counting Stars

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1622    Accepted Submission(s): 444

Problem Description
Little A is an astronomy lover, and he has found that the sky was so beautiful!

So he is counting stars now!

There are n stars in the sky, and little A has connected them by m non-directional edges.

It is guranteed that no edges connect one star with itself, and every two edges connect different pairs of stars.

Now little A wants to know that how many different "A-Structure"s are there in the sky, can you help him?

An "A-structure" can be seen as a non-directional subgraph G, with a set of four nodes V and a set of five edges E.

If V=(A,B,C,D) and E=(AB,BC,CD,DA,AC), we call G as an "A-structure".

It is defined that "A-structure" G1=V1+E1 and G2=V2+E2 are same only in the condition that V1=V2 and E1=E2.

Input
There are no more than 300 test cases.

For each test case, there are 2 positive integers n and m in the first line.

2n1051mmin(2×105,n(n1)2)

And then m lines follow, in each line there are two positive integers u and v, describing that this edge connects node u and node v.

1u,vn

n3×105,m6×105

Output
For each test case, just output one integer--the number of different "A-structure"s in one line.

Sample Input
4 51 22 33 44 11 34 61 22 33 44 11 32 4

Sample Output
16

//方法一： m * sqrt(m)
#include<bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N =1e5+5;
const ll lim=1e5+5;

int deg[N];
set<ll >se;
vector< int >ve[N];
int vis[N];
int n,m;
int _hs[N];

void init()
{
memset(vis,0,sizeof(vis));
memset(deg,0,sizeof(deg));
se.clear();
memset(_hs,0,sizeof(_hs));
for(int i=0;i<N;i++) ve[i].clear();
return ;
}

void solve()
{
int up=sqrt(1.0*m);
ll ans=0;
for(int a=1;a<=n;a++)
{
vis[a]=1;
for(int i=0;i<ve[a].size();i++) _hs[ve[a][i]]=a;
for(int i=0;i<ve[a].size();i++){
int b=ve[a][i];
if(vis[b]) continue;

ll cnt=0;
if(deg[b]<=up)
{
for(int j=0;j<ve[b].size();j++){
int c=ve[b][j];
if(_hs[c]==a) cnt++;
}
}
else{
for(int j=0;j<ve[a].size();j++){
int c=ve[a][j];
if(se.find(ll(b*lim+c))!=se.end()) cnt++;
}
}

ans=ans+cnt*(cnt-1)/2;
}
}

printf("%lld\n",ans);
}

int main()
{
while(scanf("%d %d",&n,&m)!=EOF)
{
init();
int u,v;
for(int i=1;i<=m;i++)
{
scanf("%d %d",&u,&v);
deg[u]++;
deg[v]++;
se.insert(ll(u*lim+v));
se.insert(ll(v*lim+u));
ve[u].push_back(v);
ve[v].push_back(u);
}
solve();

}
return 0;
}

//单向建图 建图完毕后为有向无环图

#include<bits/stdc++.h>
#define LL long long
using namespace std;
typedef pair<int ,int > pii;
typedef long long ll;
const int N =1e5+5;
const int M =2e5+5;
const ll lim=1e5+5;

ll cnt[M];
int deg[N];
int x[M];
int y[M];
vector<pii>ve[N];
int n,m;
int pos[N];
int jud[N];

void solve()
{
//ll tot=0;   三元环个数
for(int i=1;i<=m;i++)
{
int u=x[i]; int v=y[i];
for(int j=0;j<ve[u].size();j++){
int uu=ve[u][j].first;
int inde=ve[u][j].second;
pos[uu]=inde;
jud[uu]=i+1;
}

for(int j=0;j<ve[v].size();j++)
{
int vv=ve[v][j].first;
if(jud[vv]==i+1){
//tot++;
cnt[i]++;       // 三元环对应的三条边分别 ++
cnt[pos[vv]]++;
cnt[ve[v][j].second]++;
}
}
}

//cout<<tot<<endl;
ll ans=0;
for(int i=1;i<=m;i++){
ans=ans+cnt[i]*(cnt[i]-1)/2;
}
printf("%lld\n",ans);
}

void init()
{
for(int i=0;i<=n;i++){
deg[i]=pos[i]=jud[i]=0;
ve[i].clear();
}
}

int main()
{
while(scanf("%d %d",&n,&m)!=EOF)
{
init();
int u,v;
for(int i=1;i<=m;i++){
scanf("%d %d",&u,&v);
deg[u]++; deg[v]++;
x[i]=u;  y[i]=v;
}

for(int i=1;i<=m;i++){
cnt[i]=0;
if(deg[x[i]]<deg[y[i]]){
ve[x[i]].push_back(pii(y[i],i));
}
else if(deg[x[i]]>deg[y[i]]){
ve[y[i]].push_back(pii(x[i],i));
}
else{
if(x[i]<=y[i]){
ve[x[i]].push_back(pii(y[i],i));
}
else ve[y[i]].push_back(pii(x[i],i));
}
}
/*
for(int i=1;i<=n;i++) cout<<ve[i].size()<<" ";
cout<<endl;
*/
solve();

}
return 0;
}