├── CircuitFinder.h ├── Example.cpp └── README.md /CircuitFinder.h: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // Written by Xing Mingjie (mingjie.xing@gmail.com). 4 | // 5 | // An implementation of the Johnson's circuit finding algorithm [1]. 6 | // 7 | // [1] Donald B. Johnson, Finding all the elementary circuits of a directed 8 | // graph, SIAM Journal on Computing, 1975. 9 | // 10 | //===----------------------------------------------------------------------===// 11 | 12 | #ifndef CIRCUIT_FINDER_H 13 | #define CIRCUIT_FINDER_H 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | typedef std::list NodeList; 21 | 22 | template 23 | class CircuitFinder 24 | { 25 | std::vector AK; 26 | std::vector Stack; 27 | std::vector Blocked; 28 | std::vector B; 29 | int S; 30 | 31 | void unblock(int U); 32 | bool circuit(int V); 33 | void output(); 34 | 35 | public: 36 | CircuitFinder(int Array[N][N]) 37 | : AK(N), Blocked(N), B(N) { 38 | for (int I = 0; I < N; ++I) { 39 | for (int J = 0; J < N; ++J) { 40 | if (Array[I][J]) { 41 | AK[I].push_back(Array[I][J]); 42 | } 43 | } 44 | } 45 | } 46 | 47 | void run(); 48 | }; 49 | 50 | template 51 | void CircuitFinder::unblock(int U) 52 | { 53 | Blocked[U - 1] = false; 54 | 55 | while (!B[U - 1].empty()) { 56 | int W = B[U - 1].front(); 57 | B[U - 1].pop_front(); 58 | 59 | if (Blocked[W - 1]) { 60 | unblock(W); 61 | } 62 | } 63 | } 64 | 65 | template 66 | bool CircuitFinder::circuit(int V) 67 | { 68 | bool F = false; 69 | Stack.push_back(V); 70 | Blocked[V - 1] = true; 71 | 72 | for (int W : AK[V - 1]) { 73 | if (W == S) { 74 | output(); 75 | F = true; 76 | } else if (W > S && !Blocked[W - 1]) { 77 | F = circuit(W); 78 | } 79 | } 80 | 81 | if (F) { 82 | unblock(V); 83 | } else { 84 | for (int W : AK[V - 1]) { 85 | auto IT = std::find(B[W - 1].begin(), B[W - 1].end(), V); 86 | if (IT == B[W - 1].end()) { 87 | B[W - 1].push_back(V); 88 | } 89 | } 90 | } 91 | 92 | Stack.pop_back(); 93 | return F; 94 | } 95 | 96 | template 97 | void CircuitFinder::output() 98 | { 99 | std::cout << "circuit: "; 100 | for (auto I = Stack.begin(), E = Stack.end(); I != E; ++I) { 101 | std::cout << *I << " -> "; 102 | } 103 | std::cout << *Stack.begin() << std::endl; 104 | } 105 | 106 | template 107 | void CircuitFinder::run() 108 | { 109 | Stack.clear(); 110 | S = 1; 111 | 112 | while (S < N) { 113 | for (int I = S; I <= N; ++I) { 114 | Blocked[I - 1] = false; 115 | B[I - 1].clear(); 116 | } 117 | circuit(S); 118 | ++S; 119 | } 120 | } 121 | 122 | #endif // CIRCUIT_FINDER_H 123 | -------------------------------------------------------------------------------- /Example.cpp: -------------------------------------------------------------------------------- 1 | //===----------------------------------------------------------------------===// 2 | // 3 | // Written by Xing Mingjie (mingjie.xing@gmail.com). 4 | // 5 | // A test program for circuit finding algorithm. 6 | // 7 | //===----------------------------------------------------------------------===// 8 | 9 | 10 | /* 11 | V5 V3 12 | +-<---o---<---o---<--+ 13 | | | | 14 | V1 o ^ o V4 15 | | V2| | 16 | +------>------o--->--+ 17 | / \ 18 | | | 19 | +->-+ 20 | 21 | N = 5 22 | 23 | / 2 0 0 0 0 \ 24 | | 2 3 4 0 0 | 25 | AK = | 5 0 0 0 0 | 26 | | 3 0 0 0 0 | 27 | \ 1 0 0 0 0 / 28 | */ 29 | 30 | #include "CircuitFinder.h" 31 | 32 | int main() 33 | { 34 | int A[5][5] = { 35 | 2, 0, 0, 0, 0, 36 | 2, 3, 4, 0, 0, 37 | 5, 0, 0, 0, 0, 38 | 3, 0, 0, 0, 0, 39 | 1, 0, 0, 0, 0 40 | }; 41 | 42 | CircuitFinder<5> CF(A); 43 | CF.run(); 44 | return 0; 45 | } 46 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # circuit-finding-algorithm 2 | 3 | Written by Xing Mingjie (mingjie.xing@gmail.com). 4 | 5 | An implementation of the Johnson's circuit finding algorithm [1]. 6 | 7 | [1] Donald B. Johnson, Finding all the elementary circuits of a directed 8 | graph, SIAM Journal on Computing, 1975. 9 | 10 | ## Example 11 | 12 | $ g++ -std=c++11 Example.cpp 13 | $ ./a.out 14 | circuit: 1 -> 2 -> 3 -> 5 -> 1 15 | circuit: 1 -> 2 -> 4 -> 3 -> 5 -> 1 16 | circuit: 2 -> 2 17 | --------------------------------------------------------------------------------