Find if possible to visit every nodes in given Graph exactly once based on given conditions

Introduction

Graph theory plays a crucial part in understanding a wide run of real-world issues, counting course optimization, organize examination, and task planning. One interesting issue inside graph theory is the seek for a Hamiltonian way, a way that visits each node in a graph exactly once. This issue has applications in zones such as circuit plan, DNA sequencing, and coordination’s arranging. In this article, we dig into the investigation of diverse approaches to decide on the off chance that it is conceivable to visit each hub in a given chart precisely once, based on certain conditions. We center on three particular calculations: the Backtracking Calculation, Depth-First Look (DFS), and Backtracking with Pruning. Particularly, we show these approaches utilizing the C++ programming dialect, giving code pieces, step-by-step calculations, and yields for each method.

Approach 1: Depth-First Search (DFS)

The DFS algorithm investigates all poosible ways by navigating the chart in a depth-first way. It employments a stack to keep track of the current way and a gone to cluster to check the gone by vertices.

Algorithm

• Step 1 − Begin at the primary vertex of the graph and stamp it as gone by.

• Step 2 − Push the current vertex onto the stack and include it to the way.

• Step 3 − While the stack isn't purge −

• Pop the beat vertex from the stack.

• On the off chance that all vertices have been gone to, print the way and return genuine.

• For each adjoining vertex that has not been gone to, check it as gone by, thrust it onto the stack, and include it to the way.

• Step 4 − In case the stack gets to be empty, return false.

Example

#include <iostream>
#include <vector>
#include <stack>
#include <algorithm>

using namespace std;

bool isSafe(int v, int pos, const vector<int>& path, const vector<vector<int>>& graph) {
if (graph[path[pos - 1]][v] == 0)
return false;

for (int i = 0; i < pos; ++i)
if (path[i] == v)
return false;

return true;
}

bool dfsUtil(const vector<vector<int>>& graph, vector<int>& path, vector<bool>& visited, int pos) {
int n = graph.size();

if (pos == n) {

for (int v : path)
cout << v << " ";
cout << endl;
return true;
}

for (int v = 1; v < n; ++v) {
if (!visited[v] && isSafe(v, pos, path, graph)) {
visited[v] = true;
path[pos] = v;
if (dfsUtil(graph, path, visited, pos + 1))
return true;
visited[v] = false;
path[pos] = -1;
}
}

return false;
}

void findHamiltonianPath(const vector<vector<int>>& graph) {
int n = graph.size();
vector<int> path(n, -1);
vector<bool> visited(n, false);

visited[0] = true; // Mark the first vertex as visited
path[0] = 0;

if (!dfsUtil(graph, path, visited, 1))
cout << "No Hamiltonian path exists." << endl;
}

int main() {
vector<vector<int>> graph = {
{0, 1, 1, 1},
{1, 0, 1, 0},
{1, 1, 0, 1},
{1, 0, 1, 0}
};

cout << "Depth-First Search (DFS):" << endl;
findHamiltonianPath(graph);

return 0;
}


Output

Depth-First Search (DFS):
0 1 2 3


Approach 2 : Backtracking Algorithm

The backtracking algorithm could be a brute constraint approach that efficiently investigates all possible ways within the chart to discover a Hamiltonian way. It employments a recursive work that backtracks at whatever point it experiences a dead conclusion.

Algorithm

• Step 1 − Begin at the primary vertex of the graph.

• Step 2 − In case all vertices have been visited, print the way and return genuine.

• Step 3 − For each adjoining vertex that has not been gone to, check it as gone to and add it to the way.

• Step 4 − Recursively call the work on the following vertex within the way.

• Step 5 − If the recursive call returns genuine, the way is total. Return genuine.

• Step 6 − In case the recursive call returns untrue, backtrack by stamping the current vertex as un-visited and evacuating it from the way.

• Step 7 − In the event that no more adjoining vertices are cleared out to investigate, return untrue.

Example

#include <iostream>
#include <vector>

using namespace std;

bool isSafe(int v, int pos, const vector<int>& path, const vector<vector<int>>& graph) {
if (graph[path[pos - 1]][v] == 0)
return false;

for (int i = 0; i < pos; ++i)
if (path[i] == v)
return false;

return true;
}

bool hamiltonianPathUtil(const vector<vector<int>>& graph, vector<int>& path, int pos) {
if (pos == graph.size()) {

for (int v : path)
cout << v << " ";
cout << endl;
return true;
}

for (int v = 1; v < graph.size(); ++v) {
if (isSafe(v, pos, path, graph)) {
path[pos] = v;
if (hamiltonianPathUtil(graph, path, pos + 1))
return true;
path[pos] = -1; // Backtrack
}
}

return false;
}

void findHamiltonianPath(const vector<vector<int>>& graph) {
vector<int> path(graph.size(), -1);

if (!hamiltonianPathUtil(graph, path, 1))
cout << "No Hamiltonian path exists." << endl;
}

int main() {
vector<vector<int>> graph = {
{0, 1, 1, 1},
{1, 0, 1, 0},
{1, 1, 0, 1},
{1, 0, 1, 0}
};

cout << "Backtracking Algorithm:" << endl;
findHamiltonianPath(graph);

return 0;
}


Output

Backtracking Algorithm:
0 1 2 3


Conclusion

In conclusion, we have investigated two different approaches to determine in case it is possible to visit every node in each graph exactly once. The issue, known as the Hamiltonian Way issue, requires finding a way that visits each node within the graph precisely once, without returning to any node. To begin with, we talked about the Backtracking Calculation, which methodically explores all conceivable ways within the graph. The calculation employments recursion and backtracking to discover a substantial Hamiltonian way. Although it can be computationally costly, the Backtracking Calculation gives a direct arrangement to the issue.

Updated on: 25-Aug-2023

37 Views