-
-
Notifications
You must be signed in to change notification settings - Fork 7.3k
/
Copy pathhamiltons_cycle.cpp
147 lines (133 loc) · 4.09 KB
/
hamiltons_cycle.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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/**
* @file
* @brief The implementation of [Hamilton's
* cycle](https://en.wikipedia.org/wiki/Hamiltonian_path) dynamic solution for
* vertices number less than 20.
* @details
* I use \f$2^n\times n\f$ matrix and for every \f$[i, j]\f$ (\f$i < 2^n\f$ and
* \f$j < n\f$) in the matrix I store `true` if it is possible to get to all
* vertices on which position in `i`'s binary representation is `1` so as
* \f$j\f$ would be the last one.
*
* In the the end if any cell in \f$(2^n - 1)^{\mbox{th}}\f$ row is `true` there
* exists hamiltonian cycle.
*
* @author [vakhokoto](https://github.com/vakhokoto)
* @author [Krishna Vedala](https://github.com/kvedala)
*/
#include <cassert>
#include <iostream>
#include <vector>
/**
* The function determines if there is a hamilton's cycle in the graph
*
* @param routes nxn boolean matrix of \f$[i, j]\f$ where \f$[i, j]\f$ is `true`
* if there is a road from \f$i\f$ to \f$j\f$
* @return `true` if there is Hamiltonian cycle in the graph
* @return `false` if there is no Hamiltonian cycle in the graph
*/
bool hamilton_cycle(const std::vector<std::vector<bool>> &routes) {
const size_t n = routes.size();
// height of dp array which is 2^n
const size_t height = 1 << n;
std::vector<std::vector<bool>> dp(height, std::vector<bool>(n, false));
// to fill in the [2^i, i] cells with true
for (size_t i = 0; i < n; ++i) {
dp[1 << i][i] = true;
}
for (size_t i = 1; i < height; i++) {
std::vector<size_t> zeros, ones;
// finding positions with 1s and 0s and separate them
for (size_t pos = 0; pos < n; ++pos) {
if ((1 << pos) & i) {
ones.push_back(pos);
} else {
zeros.push_back(pos);
}
}
for (auto &o : ones) {
if (!dp[i][o]) {
continue;
}
for (auto &z : zeros) {
if (!routes[o][z]) {
continue;
}
dp[i + (1 << z)][z] = true;
}
}
}
bool is_cycle = false;
for (size_t i = 0; i < n; i++) {
is_cycle |= dp[height - 1][i];
if (is_cycle) { // if true, all subsequent loop will be true. hence
// break
break;
}
}
return is_cycle;
}
/**
* this test is testing if ::hamilton_cycle returns `true` for
* graph: `1 -> 2 -> 3 -> 4`
* @return None
*/
static void test1() {
std::vector<std::vector<bool>> arr{
std::vector<bool>({true, true, false, false}),
std::vector<bool>({false, true, true, false}),
std::vector<bool>({false, false, true, true}),
std::vector<bool>({false, false, false, true})};
bool ans = hamilton_cycle(arr);
std::cout << "Test 1... ";
assert(ans);
std::cout << "passed\n";
}
/**
* this test is testing if ::hamilton_cycle returns `false` for
* \n graph:<pre>
* 1 -> 2 -> 3
* |
* V
* 4</pre>
* @return None
*/
static void test2() {
std::vector<std::vector<bool>> arr{
std::vector<bool>({true, true, false, false}),
std::vector<bool>({false, true, true, true}),
std::vector<bool>({false, false, true, false}),
std::vector<bool>({false, false, false, true})};
bool ans = hamilton_cycle(arr);
std::cout << "Test 2... ";
assert(!ans); // not a cycle
std::cout << "passed\n";
}
/**
* this test is testing if ::hamilton_cycle returns `true` for
* clique with 4 vertices
* @return None
*/
static void test3() {
std::vector<std::vector<bool>> arr{
std::vector<bool>({true, true, true, true}),
std::vector<bool>({true, true, true, true}),
std::vector<bool>({true, true, true, true}),
std::vector<bool>({true, true, true, true})};
bool ans = hamilton_cycle(arr);
std::cout << "Test 3... ";
assert(ans);
std::cout << "passed\n";
}
/**
* Main function
*
* @param argc commandline argument count (ignored)
* @param argv commandline array of arguments (ignored)
*/
int main(int argc, char **argv) {
test1();
test2();
test3();
return 0;
}