-
Notifications
You must be signed in to change notification settings - Fork 159
/
cycle_enumeration.cc
96 lines (89 loc) · 2.27 KB
/
cycle_enumeration.cc
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
//
// Hawick and James' cycle enumeration
//
// Description:
// For a directed graph, it enumerates all cycles
//
// Algorithm:
// Hawick and James's implementation of Johnson algorithm.
//
// Complexity
// O(n+m) average time for each cycles,
// O(n+m) space.
//
// References:
// K. A. Hawick and H. A. James (2007):
// Enumerating circuits and loops in graphs with self-arcs and multiple-arcs.
// in Proceedings of International Conference on Foundations of Computer Science,
// pp.14--20.
//
// D. B. Johnson (1975):
// Finding all the elementary circuits of a directed graph.
// SIAM Journal on Computing, vol.4, pp.77--84.
//
#include <iostream>
#include <vector>
#include <cstdio>
#include <algorithm>
#include <unordered_set>
#include <functional>
using namespace std;
#define fst first
#define snd second
#define all(c) ((c).begin()), ((c).end())
#define TEST(s) if (!(s)) { cout << __LINE__ << " " << #s << endl; exit(-1); }
struct graph {
int n;
vector<vector<int>> adj;
graph(int n) : n(n), adj(n) { }
void add_edge(int u, int v) {
adj[u].push_back(v);
}
void all_cycles() {
vector<int> S;
for (int s = 0; s < n; ++s) {
vector<bool> blocked(n);
vector<unordered_set<int>> B(n);
function<void(int)> unblock = [&](int u) {
blocked[u] = false;
for (int v: B[u])
if (blocked[v]) unblock(v);
B[u].clear();
};
function<bool(int)> rec = [&](int u) {
bool is_cycle = false;
blocked[u] = true;
S.push_back(u);
for (int v: adj[u]) {
if (v < s) continue;
if (v == s) {
is_cycle = true; // S forms a cycle
cout << "found cycle" << endl;
for (auto w: S) cout << " " << w;
cout << endl;
} else if (!blocked[v] && rec(v)) is_cycle = true;
if (is_cycle) unblock(u);
else {
for (int v: adj[u]) {
if (v < s) continue;
if (!B[v].count(u)) B[v].insert(u);
}
}
}
S.pop_back();
return is_cycle;
}; rec(s);
}
}
};
int main() {
int n = 4;
graph g(n);
g.add_edge(0,1);
g.add_edge(1,2);
g.add_edge(2,0);
g.add_edge(1,3);
g.add_edge(3,0);
g.add_edge(2,3);
g.all_cycles();
}