题干:

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)V=(A,B,C,D) and E=(AB,BC,CD,DA,AC)E=(AB,BC,CD,DA,AC), we call G as an "A-structure". 

It is defined that "A-structure" G1=V1+E1G1=V1+E1 and G2=V2+E2G2=V2+E2 are same only in the condition that V1=V2V1=V2 and E1=E2E1=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. 

2≤n≤1052≤n≤105, 1≤m≤min(2×105,n(n−1)2)1≤m≤min(2×105,n(n−1)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. 

1≤u,v≤n1≤u,v≤n 

∑n≤3×105∑n≤3×105,∑m≤6×105∑m≤6×105 

Output

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

Sample Input

4 5
1 2
2 3
3 4
4 1
1 3
4 6
1 2
2 3
3 4
4 1
1 3
2 4

Sample Output

1
6

题目大意:

【HDU - 6184】Counting Stars(三元环计数,二分,优化暴力,O(m*sqrt(m)),图论)_i++    【HDU - 6184】Counting Stars(三元环计数,二分,优化暴力,O(m*sqrt(m)),图论)_#include_02

解题报告:

暴力。这题主要是卡空间了啊不然随便搞的。。然后卡空间了变成怎么交都MLE、、、

对于题干,不难想到就是问有多少个双三元环,所有我们枚举每一条边,然后能构成的所有三元环个数假设x,那就是C(2,x)就是这条边的贡献。

暴力每个点i,然后枚举他的所有边获得点j,然后对于第三个点k分两种情况讨论:

①如果j的临边数目少于【HDU - 6184】Counting Stars(三元环计数,二分,优化暴力,O(m*sqrt(m)),图论)_i++_03,那么直接暴力就好,复杂度【HDU - 6184】Counting Stars(三元环计数,二分,优化暴力,O(m*sqrt(m)),图论)_#include_04

②如果临边数目大于【HDU - 6184】Counting Stars(三元环计数,二分,优化暴力,O(m*sqrt(m)),图论)_i++_03,(这样的点一定不会多于【HDU - 6184】Counting Stars(三元环计数,二分,优化暴力,O(m*sqrt(m)),图论)_i++_03的复杂度  个)那么暴力i的邻接点,二分判断有没有就可以了。

这样保证总复杂度【HDU - 6184】Counting Stars(三元环计数,二分,优化暴力,O(m*sqrt(m)),图论)_#include_07

好像还有更优秀的做法:​​参考博客​

AC代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define F first
#define S second
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
typedef pair<int,int> PII;
const int MAX = 2e5 + 5;
vector<int> vv[MAX];
int e[MAX];
int n,m;
int main()
{
while(~scanf("%d%d",&n,&m)) {
for(int i = 1; i<=n; i++) e[i] = -1,vv[i].clear();
for(int u,v,i = 1; i<=m; i++) {
scanf("%d%d",&u,&v);
if(u>v) swap(u,v);
vv[u].pb(v);
vv[v].pb(u);
}
for(int i = 1; i<=n; i++) sort(vv[i].begin(),vv[i].end());
int SQRT = sqrt(m);
ll ans = 0;
for(int i = 1; i<=n; i++) {
for(auto j : vv[i]) e[j] = i;
for(auto j : vv[i]) {
if(j > i) {
int sz = vv[j].size(),cnt = 0;
if(sz <= SQRT) {
for(auto k : vv[j]) cnt += e[k] == i;
}
else {
for(auto k : vv[i]) cnt += binary_search(vv[k].begin(),vv[k].end(),j);
}
ans += 1LL*cnt*(cnt-1)/2;
}
}
}
printf("%lld\n",ans);
}
return 0 ;
}

还有一个问题啊、、为什么sz<SQRT的话,就一直报TLE啊????欢迎来讨论、、、

改成严格的msqrtm的算法:(建有向边)

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define FF first
#define SS second
#define ll long long
#define pb push_back
#define pm make_pair
using namespace std;
typedef pair<int,int> PII;
const int MAX = 2e5 + 5;
int cnt[MAX];
int U[MAX],V[MAX],du[MAX];
vector<PII> vv[MAX];
PII e[MAX];
int n,m;
int main()
{
while(~scanf("%d%d",&n,&m)) {
for(int i = 1; i<=n; i++) du[i] = 0,e[i].FF = 0,vv[i].clear();
for(int i = 1; i<=m; i++) cnt[i] = 0;
for(int i = 1; i<=m; i++) scanf("%d%d",U+i,V+i),du[U[i]]++,du[V[i]]++;
for(int u,v,i = 1; i<=m; i++) {
u = U[i],v = V[i];
if(du[u] > du[v]) vv[v].pb(pm(u,i));
else if(du[u] < du[v]) vv[u].pb(pm(v,i));
else {
if(u<v) vv[u].pb(pm(v,i));
else vv[v].pb(pm(u,i));
}
}
for(int u,v,i = 1; i<=m; i++) {
u = U[i],v = V[i];
for(auto x : vv[u]) e[x.FF] = pm(i,x.SS);
for(auto x : vv[v]) {
if(e[x.FF].FF == i) cnt[i]++,cnt[x.SS]++,cnt[e[x.FF].SS]++;
}
}
ll ans = 0;
for(int i = 1; i<=m; i++) ans += 1LL*cnt[i]*(cnt[i]-1)/2;
printf("%lld\n",ans);
}
return 0 ;
}