-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathTriangle counting in graphs.cpp
110 lines (102 loc) · 2.76 KB
/
Triangle counting in graphs.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
//
// main.cpp
// practice
//
// Created by Mahmud on 01/07/19.
// Copyright © 2018 Mahmud. All rights reserved.
//
/*
Fast triangle counting for graphs
O(M * sqrt(M)) compexity where M is the edge size of the graph
Note that: The implementation removes multiple edges
and do not consider same triples more than once.
*/
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <set>
#include <bitset>
#include <utility>
#include <functional>
#include <numeric>
using namespace std;
const int MAX_SIZE = 1 << 17;
int N, M;
int degrees[MAX_SIZE];
vector<pair<int, int>> edgeList;
vector<vector<int>> graph;
bitset<MAX_SIZE> adj[MAX_SIZE];
int main(int argc, const char * argv[]) {
scanf("%d%d", &N, &M);
for (int i = 0; i < M; i ++) {
int u, v;
scanf("%d%d", &u, &v);
edgeList.push_back(make_pair(u, v));
}
sort(edgeList.begin(), edgeList.end());
edgeList.erase(unique(edgeList.begin(), edgeList.end()), edgeList.end());
graph.resize(N + 1);
for (auto edge: edgeList) {
int u = edge.first;
int v = edge.second;
graph[u].push_back(v);
graph[v].push_back(u);
adj[u][v] = 1;
adj[v][u] = 1;
degrees[u] ++;
degrees[v] ++;
}
int threshold = (int)sqrt(1. * M);
vector<int> heavyNodes;
for (int i = 1; i <= N; i ++) {
if (degrees[i] >= threshold) {
heavyNodes.push_back(i);
}
}
vector<int> isHeavy(N + 1, 0);
for (int i: heavyNodes) {
isHeavy[i] = 1;
}
vector<int> orders(N + 1);
iota(orders.begin(), orders.end(), 1);
sort(orders.begin(), orders.end(), [&](int u, int v) {
if (degrees[u] != degrees[v]) {
return degrees[u] < degrees[v];
} else {
return u < v;
}
});
long long result = 0;
for (int i = 0; i < (int)heavyNodes.size(); i ++) {
for (int j = i + 1; j < (int)heavyNodes.size(); j ++) {
for (int k = j + 1; k < (int)heavyNodes.size(); k ++) {
int a = heavyNodes[i];
int b = heavyNodes[j];
int c = heavyNodes[k];
if (adj[a][b] && adj[a][c] && adj[b][c]) {
result ++;
}
}
}
}
for (auto edge: edgeList) {
int u = edge.first;
int v = edge.second;
if (isHeavy[u] && isHeavy[v]) {
continue;
} if (orders[u] > orders[v]) {
swap(u, v);
}
for (auto neighbor: graph[u]) {
if (orders[neighbor] < orders[u]) {
continue;
} if (adj[v][neighbor]) {
result ++;
}
}
}
cout << result << endl;
return 0;
}