Find all Hamiltonian Cycles using BFS - c++

I know there's so many threads about this topic, but none of the ones I have found had helped me.
I have to find all the Hamiltonian cycles on a undirected graph using BFS. I have the code that search for a cycle (not hamiltonian), now I need to modify it and here's my problem. I'm not sure how to do this in a proper manner without thinking recursiverly.
My thoughts are that in order to find all Hamiltonian cycles using BFS I need:
Keep a track of one possible cycle (path).
Keep a count of the numbers of visited nodes. If I arrive to a "n" node that has the source as parent, I will need to check if all nodes are already visited.
So, in order to have a Hamiltonian Cycle, I must visit all nodes only once and finish when I arrive to a node that is inside of visited ones and that has "source" as adjacent.
Here's my graph.
https://i.stack.imgur.com/siLDn.png
And here's my code
#include <bits/stdc++.h>
using namespace std;
void addEdge(vector<int> adj[], int u, int v)
{
adj[u].push_back(v);
adj[v].push_back(u);
}
// return true if there's a cycle on the graph
bool thereIsCycle(vector<int> adj[], int s, int V)
{
// Mark all the vertices as not visited
vector<bool> visited(V, false);
// Set parent vertex for every vertex as -1.
vector<int> parent(V, -1);
// Create a queue for BFS
queue<int> q;
// Mark the current node as
// visited and enqueue it
visited[s] = true;
q.push(s);
while (!q.empty()) {
// Dequeue a vertex from queue and print it
int u = q.front();
q.pop();
// Get all adjacent vertices of the dequeued
// vertex u. If a adjacent has not been visited,
// then mark it visited and enqueue it. We also
// mark parent so that parent is not considered
// for cycle.
for (auto v : adj[u]) {
if (!visited[v]) {
visited[v] = true;
q.push(v);
parent[v] = u;
}
else if (parent[u] != v){
return true;
}
}
}
return false;
}
int main()
{
int V = 4;
vector<int> adj[V];
addEdge(adj, 0, 1);
addEdge(adj, 1, 2);
addEdge(adj, 2, 0);
addEdge(adj, 2, 3);
// check if there is a cycle from node 0
if (thereIsCycle(adj, 0, V)){
cout << "Yes";
}else{
cout << "No";
}
return 0;
}
Any suggests? Thank you all.

It looks like your code is currently looking for simple (non-Hamiltonian) cycles in the graph. If we add to the condition if (parent[u] != v){ return true; } checking that all vertices have been visited (all elements of the visited must be true), then it looks like the code will work correctly.

addEdge is not doing what you think it is.
Adj is intended to be the adjacency matrix of the graph. As implied by matrix this needs to be two dimensional.
2 for (auto v : adj[u]) makes no sense. adj[u] is an int, so it is meaningless to 'iterate' over it.
My suggestion: Take a step back and get the fundamentals right before tackling such an advanced problem. Create an actual graph class based on a correctly implemented adjacency matrix. Test you class with something simple, say listing all reachable nodes using BFS. Once that is working you can begin to move onto bigger challenges.

Related

Difference between range-based for loop and normal for loop Depth-First Search implementation

I'm trying to implement a depth first search algorithm for a graph data structure and my function looks like this:
void dfs(int x, vector <v_Int>& Adjacency_List, v_Int& visited) {
visited[x] = 1; //Mark current vertex as visited
for (int i = 0; i < Adjacency_List[x].size(); i++) { //Iterate through all neighbours of vertex x
if (visited[i] != 1) { //If neighbour not visited, recursively go there
dfs(i, Adjacency_List, visited);
}
}
}
When I used a normal for loop like I did above, the visited array does not get updated beyond the first vertex of the graph when I call the function dfs(0, Adjacency_List, visited);
However, when I change the normal for loop to a range based for loop like so:
for (auto &v : Adjacency_List[x]) { //Iterate through all neighbours of vertex x
if (!visited[v]) {
dfs(v, Adjacency_List, visited); //If neighbour not visited, recursively go there
}
}
The visited array gets updated accordingly whenever the dfs function is called. I'm not too sure why the 2nd implementation works but my initial implementation doesn't since both implementations seem to have similar logics. Thank you for your help!
Edit: v_Int is a typedef I declared to be a vector of integers
In first implementation, neighbour is not i, its Adjacency_List[x][i].
int neighbour = Adjacency_List[x][i];
if (visited[neighbour] != 1) { //If neighbour not visited, recursively go there
dfs(neighbour, Adjacency_List, visited);
}

Shortest route modification

Is there a way to modify this to show the route of the shortest path? For example, if i had a list of numbers like (3,1),(3,0),(4,3),(2,1) the output for getting from 4 to 1 would be 4->3,3->1
// Prints shortest paths from src to all other vertices
void Graph::shortestPath(int src)
{
// Create a priority queue to store vertices that
// are being preprocessed. This is weird syntax in C++.
// Refer below link for details of this syntax
// http://geeksquiz.com/implement-min-heap-using-stl/
priority_queue< iPair, vector <iPair> , greater<iPair> > pq;
// Create a vector for distances and initialize all
// distances as infinite (INF)
vector<int> dist(V, INF);
// Insert source itself in priority queue and initialize
// its distance as 0.
pq.push(make_pair(0, src));
dist[src] = 0;
/* Looping till priority queue becomes empty (or all
distances are not finalized) */
while (!pq.empty())
{
// The first vertex in pair is the minimum distance
// vertex, extract it from priority queue.
// vertex label is stored in second of pair (it
// has to be done this way to keep the vertices
// sorted distance (distance must be first item
// in pair)
int u = pq.top().second;
pq.pop();
// 'i' is used to get all adjacent vertices of a vertex
list< pair<int, int> >::iterator i;
for (i = adj[u].begin(); i != adj[u].end(); ++i)
{
// Get vertex label and weight of current adjacent
// of u.
int v = (*i).first;
int weight = (*i).second;
// If there is shorted path to v through u.
if (dist[v] > dist[u] + weight)
{
// Updating distance of v
dist[v] = dist[u] + weight;
pq.push(make_pair(dist[v], v));
}
}
}
// Print shortest distances stored in dist[]
printf("Vertex Distance from Source\n");
for (int i = 0; i < V; ++i)
printf("%d \t\t %d\n", i, dist[i]);
}
Putting in an array that stores the numbers of the path like 4,3,3,1 (using above example) seems like the best idea but i don't know where to insert the array in this code to do that.
Just as you save the distances for each vertex in the dist vector, save the predecessor vertex that last updated it in a vector called predecessor.
vector<int> dist(V, INF);
vector<int> predecessor(V, 0);
Then whenever you update the distance, update the predecessor:
dist[v] = dist[u] + weight;
predecessor[v] = u;
Finally, you can trace for any vertex the shortest path (Backward) to the source:
printf("Vertex Distance from Source shortest path from source\n");
for (int i = 0; i < V; ++i)
{
printf("%d \t\t %d\t\t", i, dist[i]);
int j = i;
do
{
printf("%d,", j);
j = predecessor[j];
} while(j != src);
printf("\n");
}
Sounds like a homework problem.
Your idea to store the numbers of the path would be great, if this were a DFS. Unfortunately, Djikstra's algorithm doesn't naturally keep track of the path like a DFS does; it simply takes the next closest node and updates the distance values. It's probably more similar to a BFS in that regard.
What you could do is as you update the distances to each node, somehow store which node you're coming from (maybe in your iPair struct if you're allowed to, maybe in a map/array if you have a way to ID your nodes). I'll call it a "from" reference for the sake of this post. Then, each time you find a shorter path to a node, you can also update that from reference.
How do you find the path to a given node then? Simple: just start at the end node, and follow the "from" references back to the source.

How to do a DFS on a tree? (not necessarily binary)

I have a tree of n nodes (labeled 0 to n). I used two vectors to hold the edge information.
typedef std::vector<std::vector<int>> graph;
The input is n-1 edges in the form:
0 1
1 2
2 3
and so on
I'm told node 0 is always the root node.
I scan the edges using the following:
for (int i = 0; i < n-1; i++) {
scanf("%d %d", &a, &b);
g[a].push_back(b);
g[b].push_back(a); // the second approach doesn't use this line
}
This is my simple dfs:
void dfs(graph &g, int v) {
std::vector<int> visited; // I don't use a visited array for the second approach
for (int i = 0; i < g.size(); i++) {
visited.push_back(0);
}
std::stack<int> s;
std::set<int> t;
s.push(v);
while (!s.empty()) {
int i = s.top(); s.pop();
// do stuff
for (int i = 0; i < g[v].size(); i++) {
if (!visited[i]) {
visited[i] = true;
s.push(g[v][i]);
}
}
}
}
For example say we have 4 nodes and the following edges:
0 1
0 2
3 2
2 4
Say that I'm interested in the sub tree starting at 2. The above approach won't work because I'm inserting undirected edges 0 2 and 2 0. So when I start my dfs at 2 I add node 0 to my stack which is wrong.
I tried another approach of only inserting the edges given only but that also didn't work because in the example I would've inserted 3 2 which is an edge from 3 to node 2 and so when I start my dfs at node 2 I won't be able to reach node 3.
I feel like the problem is simple and I'm missing some big idea!
Since your graph is a rooted tree, you can do the following preprocessing.
Start a DFS from root (vertex #0);
For each vertex u, store its parent v. It means that if you travel alongside shortest path from root to u, the second-to-last vertex on this path will be v. Notice that in any tree there is exactly one shortest path from one vertex to another. Let's say that you have an array parent such that parent[u] = v according to above definition, and parent[0] = -1.
You can compute parent array by noticing, that if you do s.push(g[v][i]), then v is the parent of i (otherwise you would have visited i first);
Since parent[v] is the previous vertex on shortest path from global root (vertex 0), it is also the previous vertex on shortest path from any vertex x, which contains v in its subtree.
Now when you want to DFS over subtree of vertex u, you do DFS as you do it now, but do not visit the parent of any vertex. Say, if you want to do s.push(v), while parent[u] = v, do not do it. This way you will never leave the subtree of u.
Actually, knowing parent, you can get rid of your visited array. When you "do stuff" with vertex v, the only neighbour of v that is already visited is parent[v]. This property does not depend on the initial vertex, whose subtree you want to traverse. The DFS code would look like this (assuming you've done preprocessing to obtain parent:
void dfs(graph &g, vector<int> &parent, int v) {
std::stack<int> s;
s.push(v);
while (!s.empty()) {
int v = s.top(); s.pop(); // By the way, you have mistake here: int i = s.top().
// do stuff
for (int i = 0; i < g[v].size(); i++) {
if (parent[v] != g[v][i]) {
s.push(g[v][i]);
}
}
}
}
PS This approach is somehow similar to your second approach: it only treats edges that go from root to subtree. But it does not have the flaw, such as in your example with "3 2" being the wrong direction, because you infer direction algorithmically by doing DFS from root.

Depth First Search: Formatting output?

If I have the following graph:
Marisa Mariah
\ /
Mary---Maria---Marian---Maryanne
|
Marley--Marla
How should be Depth First Search function be implemented such that I get the output if "Mary" is my start point ?
Mary
Maria
Marisa
Mariah
Marian
Maryanne
Marla
Merley
I do realize that the number of spaces equal to depth of the vertex( name ) but I don't how to code that. Following is my function:
void DFS(Graph g, Vertex origin)
{
stack<Vertex> vertexStack;
vertexStack.push(origin);
Vertex currentVertex;
int currentDepth = 0;
while( ! vertexStack.empty() )
{
currentVertex = vertexStack.top();
vertexStack.pop();
if(currentVertex.visited == false)
{
cout << currentVertex.name << endl;
currentVertex.visited = true;
for(int i = 0; i < currentVertex.adjacencyList.size(); i++)
vertexStack.push(currentVertex.adjacencyList[i]);
}
}
}
Thanks for any help !
Just store the node and its depth your stack:
std::stack<std::pair<Vertex, int>> vertexStack;
vertexStack.push(std::make_pair(origin, 0));
// ...
std::pair<Vertex, int> current = vertexStack.top();
Vertex currentVertex = current.first;
int depth = current.second;
If you want to get fancy, you can extra the two values using std::tie():
Vertex currentVertex;
int depth;
std::tie(currentVertex, depth) = vertexStack.top();
With knowing the depth you'd just indent the output appropriately.
The current size of your stack is, BTW, unnecessarily deep! I think for a complete graph it may contain O(N * N) elements (more precisely, (N-1) * (N-2)). The problem is that you push many nodes which may get visited.
Assuming using an implicit stack (i.e., recursion) is out of question (it won't work for large graphs as you may get a stack overflow), the proper way to implement a depth first search would be:
push the current node and edge on the stack
mark the top node visited and print it, using the stack depth as indentation
if there is no node
if the top nodes contains an unvisited node (increment the edge iterator until such a node is found) go to 1.
otherwise (the edge iterator reached the end) remove the top node and go to 3.
In code this would look something like this:
std::stack<std::pair<Node, int> > stack;
stack.push(std::make_pair(origin, 0));
while (!stack.empty()) {
std::pair<Node, int>& top = stack.top();
for (; top.second < top.first.adjacencyList.size(); ++top.second) {
Node& adjacent = top.first.adjacencyList[top.second];
if (!adjacent.visited) {
adjacent.visted = true;
stack.push(std::make_pair(adjacent, 0));
print(adjacent, stack.size());
break;
}
}
if (stack.top().first.adjacencyList.size() == stack.top().second) {
stack.pop();
}
}
Let Rep(Tree) be the representation of the tree Tree. Then, Rep(Tree) looks like this:
Root
<Rep(Subtree rooted at node 1)>
<Rep(Subtree rooted at node 2)>
.
.
.
So, have your dfs function simply return the representation of the subtree rooted at that node and modify this value accordingly. Alternately, just tell every dfs call to print the representation of the tree rooted at that node but pass it the current depth. Here's an example implementation of the latter approach.
void PrintRep(const Graph& g, Vertex current, int depth)
{
cout << std::string(' ', 2*depth) << current.name << endl;
current.visited = true;
for(int i = 0; i < current.adjacencyList.size(); i++)
if(current.adjacencyList[i].visited == false)
PrintRep(g, current.adjacencyList[i], depth+1);
}
You would call this function with with your origin and depth 0 like this:
PrintRep(g, origin, 0);

Maze solver using graph traversal algorithms

In my class I have an assignment directed as follows:
In this lab, you will implement a Maze Solver, using a variety of graph-search algorithms.
Implement a templated Graph data structure, implementing the following functionality:
Add Node
Add Adjacency (given node, and adjacent node)
Breadth-First Search
Depth-First Search
Dijkstra’s Shortest Path Algorithm
To evaluate this data structure, write a program that reads a data file (with the filename passed as a command line parameter) and populates the data structure.
A set of mazes will be provided in doc sharing.
Maze Data Format
The maze data files will be text files containing integers.
The first line gives the size of the maze, in ‘cells’, x first, then y, separated by a space.
The second line gives the coordinates of the ‘start’ of the maze (x, then y, separated by a space)
The third line gives the coordinates of the ‘end’ of the maze (x, then y, separated by a space
The remainder of the file is a grid of numbers the size of the maze, space separated, where each number represents an ‘open’ (0) or ‘closed’(1) cell. Your ‘player’ can move into open cells, but not closed cells.
For various provided mazes, evaluate the execution time of each algorithm and the final path length (number of nodes opened to find the path). Record this data, by dataset size (total number of cells in the maze).
First, I don't even know how to implement a graph in the first place. All the reference that I can find just tells me what a graph is but not how to even start coding it. Do I create a class or struct like in a linked list or tree? I have no idea on what I am supposed to do.
Here is what I have so far:
#include <list>
#include <map>
#include <queue>
template <typename T>
class Graph
{
T V; //vertices
list<T> *adj; //edges;
public:
Graph(T V); //constructor
void addEdge(T v, T w); //function to add an edge to the graph
void BFS(T s); //prints the bfs traversal
};
Graph(T V)
{
this->V = V;
adj = new list<T>[V];
}
void Graph::addEdge(T v, T w)
{
adj[v].push_back(w); //Add w to v's list
}
void Graph::BFS(T s)
{
//Mark all the vertices as not visited
bool *visited = new bool[V];
for (int i - 0; i<V; i++)
visited[i] = false;
// create a queue for BFS
list<int>queue;
//Mark the current node as visited and enque it
visited[s] = true;
queue.push_back(s);
//i will be used to get all adjacent vertices of a vertex
list<T>::iterator i;
while (!queue.empty())
{
//deque a vertex from queue and print it
s = queue.front();
cout << s << " ";
queue.pop_front();
for (i = adj[s].begin(); i != adj[s].end(); i++)
{
if (!visited[*i])
{
visited[*i] = true;
queue.push_back();
}
}
}
}
Please excuse the formatting as I never used this site and I dont know how to properly place a block of code