mirror of
https://hub.njuu.cf/TheAlgorithms/C-Plus-Plus.git
synced 2023-10-11 13:05:55 +08:00
[feature] hamilton cycle dynamic programming solution in O(2^n*n) time and memory (#972)
* hamilton cycle dynamic programming solution in O(2^n*n) time and memory for n <= 20(n is number of vertices) * tests added in hamilton-cycle * stylistical fixes * endline added * assert for tests added * some more fixes delete replaced with delete[] and comment extended od main function * comments added like about author * file descriptions added in hamiltons-cycle.cpp * fix code per standards * fix filename per repo standards * code optimized * updating DIRECTORY.md * fixes: docs + optimization * fix pre * update main function docs * move file from dynamic_programming to more appropriate graph * updating DIRECTORY.md * fix filename * updating DIRECTORY.md Co-authored-by: vakhokoto <v.kotoreishvili@gmail.com> Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com>
This commit is contained in:
parent
dcf5fa4241
commit
9eca384c79
@ -81,6 +81,7 @@
|
||||
* [Dfs](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/dfs.cpp)
|
||||
* [Dfs With Stack](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/dfs_with_stack.cpp)
|
||||
* [Dijkstra](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/dijkstra.cpp)
|
||||
* [Hamiltons Cycle](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/hamiltons_cycle.cpp)
|
||||
* [Kosaraju](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/kosaraju.cpp)
|
||||
* [Kruskal](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/kruskal.cpp)
|
||||
* [Lca](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/graph/lca.cpp)
|
||||
|
147
graph/hamiltons_cycle.cpp
Normal file
147
graph/hamiltons_cycle.cpp
Normal file
@ -0,0 +1,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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user