#include <iostream>
#include <omp.h>
#include <vector>
#include <queue>
#include <chrono>
using namespace std;
class Graph {
vector<vector<int>> adjMatrix;
vector<int> visited;
int n;
public:
void accept();
void display();
void reset();
void parallelDFS(int v);
void parallelBFS(int v);
void normalDFS(int v);
void normalBFS(int v);
};
void Graph::accept() {
cout << "\nEnter the number of vertices: ";
cin >> n;
adjMatrix.resize(n, vector<int>(n, 0));
visited.resize(n, 0);
cout << "\nEnter the adjacency matrix:\n";
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cin >> adjMatrix[i][j];
}
}
}
void Graph::display() {
cout << "\nThe Adjacency Matrix is:\n";
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
cout << adjMatrix[i][j] << " ";
}
cout << endl;
}
}
void Graph::reset() {
fill(visited.begin(), visited.end(), 0);
}
void Graph::normalDFS(int v) {
cout << v << " ";
visited[v] = 1;
for (int i = 0; i < n; i++) {
if (adjMatrix[v][i] == 1 && visited[i] == 0) {
normalDFS(i);
}
}
}
void Graph::parallelDFS(int v) {
cout << v << " ";
visited[v] = 1;
#pragma omp parallel for
for (int i = 0; i < n; i++) {
if (adjMatrix[v][i] == 1 && visited[i] == 0) {
#pragma omp critical
{
if (visited[i] == 0) {
parallelDFS(i);
}
}
}
}
}
void Graph::normalBFS(int v) {
queue<int> q;
visited[v] = 1;
q.push(v);
while (!q.empty()) {
int curr = q.front();
q.pop();
cout << curr << " ";
for (int i = 0; i < n; i++) {
if (adjMatrix[curr][i] == 1 && visited[i] == 0) {
visited[i] = 1;
q.push(i);
}
}
}
}
void Graph::parallelBFS(int v) {
queue<int> q;
visited[v] = 1;
q.push(v);
while (!q.empty()) {
int curr = q.front();
q.pop();
cout << curr << " ";
#pragma omp parallel for
for (int i = 0; i < n; i++) {
if (adjMatrix[curr][i] == 1 && visited[i] == 0) {
#pragma omp critical
{
if (visited[i] == 0) {
visited[i] = 1;
q.push(i);
}
}
}
}
}
}
int main() {
Graph g;
int choice;
char cont;
do {
cout << "\nMenu\n1: Accept & Display\n2: DFS Comparison\n3: BFS Comparison\nEnter your choice: ";
cin >> choice;
switch (choice) {
case 1:
g.accept();
g.display();
break;
case 2: {
g.reset();
cout << "\nNormal DFS starting from vertex 0:\n";
auto startNormalDFS = chrono::high_resolution_clock::now();
g.normalDFS(0);
auto endNormalDFS = chrono::high_resolution_clock::now();
chrono::duration<double> normalDFSTime = endNormalDFS - startNormalDFS;
g.reset();
cout << "\n\nParallel DFS starting from vertex 0:\n";
auto startParallelDFS = chrono::high_resolution_clock::now();
g.parallelDFS(0);
auto endParallelDFS = chrono::high_resolution_clock::now();
chrono::duration<double> parallelDFSTime = endParallelDFS - startParallelDFS;
cout << "\n\nTime taken for Normal DFS: " << normalDFSTime.count() << " seconds";
cout << "\nTime taken for Parallel DFS: " << parallelDFSTime.count() << " seconds\n";
break;
}
case 3: {
g.reset();
cout << "\nNormal BFS starting from vertex 0:\n";
auto startNormalBFS = chrono::high_resolution_clock::now();
g.normalBFS(0);
auto endNormalBFS = chrono::high_resolution_clock::now();
chrono::duration<double> normalBFSTime = endNormalBFS - startNormalBFS;
g.reset();
cout << "\n\nParallel BFS starting from vertex 0:\n";
auto startParallelBFS = chrono::high_resolution_clock::now();
g.parallelBFS(0);
auto endParallelBFS = chrono::high_resolution_clock::now();
chrono::duration<double> parallelBFSTime = endParallelBFS - startParallelBFS;
cout << "\n\nTime taken for Normal BFS: " << normalBFSTime.count() << " seconds";
cout << "\nTime taken for Parallel BFS: " << parallelBFSTime.count() << " seconds\n";
break;
}
default:
cout << "Invalid choice!";
}
cout << "\nDo you want to continue? (y/n): ";
cin >> cont;
} while (cont == 'y' || cont == 'Y');
return 0;
}