Finding the cycle in a directed graph - c++

I was solving a problem to determine whether a graph contains a cycle. I solved it using the coloring method (in the visited array I will mark, 0 if it has never visited, 1 if it is visited, and 2 if the tour of vertex is done)
for this I wrote the code:
#include <bits/stdc++.h>
using namespace std;
vector<int> adj[20005];
int vis[20005];
int chk = 0;
void dfs(int u){
if(vis[u]==1) {
chk = 1;
return;
}
if(vis[u]==2) return;
vis[u] = 1;
for(auto v:adj[u]) dfs(v);
vis[u] = 2;
}
int main(){
int N, M; cin>>N>>M;
for(int i = 0; i<M; i++){
int p, q; cin>>p>>q;
adj[p].push_back(q);
}
for(int i = 1; i<=N; i++){
if(vis[i]==1) break;
if(!vis[i]) dfs(i);
}
cout<<(chk?"Yes\n":"No\n");
}
Now, I'm thinking, if there's a way to write the cycle which has been detected. I know most people will say DFS and backtracking and it's very intuitive. But want to know how do I implement it.

par[v] - parent node of v, pr - previously visited node:
void dfs(int u, int pr = -1){
if(vis[u]==1) {
vector<int> cycle();
int cur = pr;
while(cur != u) {
cycle.push_back(cur);
cur = par[cur]
}
cycle.push_back(u);
chk = 1;
return;
}
if(vis[u]==2) return;
vis[u] = 1;
par[u] = pr;
for(auto v:adj[u]) dfs(v, u);
vis[u] = 2;
}

Related

Why is my code to detect a cycle in a graph not printing anything?

I have written the code to check if a cycle exists or not in a graph using breadth-first traversal.
If I declare the adjacency list as vectoradj[n]; then it's okay.
But the problem arises when I use vector<vector>adj(n)
Can someone tell me what is the error? and how can I use the latter option to run my code?
#include <bits/stdc++.h>
using namespace std;
bool checkForCycle(int s, int V, vector<vector<int>>adj, vector<int> &visited)
{
queue<pair<int, int>> q;
visited[s] = true;
q.push({s, -1});
while (!q.empty())
{
int node = q.front().first;
int par = q.front().second;
q.pop();
for (auto it : adj[node])
{
if (!visited[it])
{
visited[it] = true;
q.push({it, node});
}
else if (par != it)
return true;
}
}
return false;
}
bool isCycle(int V,vector<vector<int>>adj)
{
vector<int> vis(V - 1, 0);
for (int i = 1; i <= V; i++)
{
if (!vis[i])
{
if (checkForCycle(i, V, adj, vis))
return true;
}
}
}
int main() {
int n, m;
cout<<"Enter number of vertices :\n";
cin>>n;
cout<<"Enter number of edges :\n";
cin>>m;
vector<vector<int>>adj(n);
for(int i=0; i<m; i++) {
int u, v;
cin>>u>>v;
adj[u].push_back(v);
adj[v].push_back(u);
}
cout<<endl;
if(isCycle(n,adj))
cout<<"cycle present int the graph";
else
cout<<"No cycle present";
return 0;
}
okay so the error resolves if I use
vector<vector<int>>adj(n+1);
instead of
vector<vector<int>>adj(n);

How to use a queue to count the number of graph components?

I have the queue functions and I have to use them to count the number of graph components. These are my functions:
struct TQueue {
int value;
TQueue * next;
};
void QueueInit(TQueue * & a_head, TQueue * & a_tail) {
a_head = NULL;
a_tail = NULL;
};
bool IsQueueEmpty(TQueue * a_head) {
return !a_head;
};
void Enqueue(TQueue * & a_head, TQueue * & a_tail, int a_val) {
TQueue * l_hlp = new TQueue;
l_hlp->value = a_val;
l_hlp->next = NULL;
if (a_tail) a_tail->next = l_hlp;
if (!a_head) a_head = l_hlp;
a_tail = l_hlp;
}
int Dequeue(TQueue * & a_head, TQueue * & a_tail) {
int l_val = a_head->value;
TQueue * l_hlp = a_head;
a_head = a_head->next;
if (!a_head) a_tail = NULL;
delete l_hlp;
return l_val;
};
void EmptyQueue(TQueue * & a_head, TQueue * & a_tail) {
TQueue * l_hlp;
while (a_head) {
l_hlp = a_head;
a_head = a_head->next;
delete l_hlp;
}
a_tail = NULL;
};
And this is my main() function and some variables:
// constant - number of vertexes
const int n = 9;
// queue declaration
TQueue *phead, *ptail;
QueueInit(phead, ptail);
// array of distanc
int dist[n];
// distanc array initialization
for (int i = 0; i < n; i++) dist[i] = -1;
// current distance
int d = 0;
// processingvertex
int v;
// number of components
int c = 0;
I prefer to use stack and DFS but it's a school projec so I must to use queue and BFS algorithm.
The approach is same as you would do in a dfs based approach. Here is a general bfs implementation using queue which you can modify easily for your purpose(i.e.using a custom queue)
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
void bfs(int src, vector<bool>& vis, vector<vector<int>>& adj) {
queue<int> q;
q.push(src);
vis[src] = true;
while(!q.empty()) {
int u = q.front(); q.pop();
vis[u] = true;
for(int v : adj[u]) {
if(!vis[v]) q.push(v);
}
}
}
int main() {
int n, m;
cin >> n >> m;
vector<vector<int>> adj(n);
for(int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
adj[u].push_back(v);
adj[v].push_back(u);
}
int count = 0;
vector<bool> vis(n);
for(int i = 0; i < n; i++) {
if(!vis[i]) {
bfs(i, vis, adj);
count++;
}
}
cout << count << '\n';
}
Variables reference
n : number of nodes in graph
m : number of edges in graph
adj : adjacency list representation of graph
vis : array to store if node is visited or not
count : number of connected components in graph
Example Test Case
Input:
6 3
1 5
0 2
2 4
Output:
3
You can refer to this post on mathematics stack exchange for understanding the algorithm: Finding connected components in a graph using BFS
This is my attempt to code compute components and assign vertices to components:
for (int i = 0; i <= n - 1; i++) visited[i] = false;
c = 0;
while (1) {
c++;
all = true;
for (int i = 0; i < n; i++)
if (!visited[i]) {
all = false;
visited[i] = c;
fronta::Enqueue(phead, ptail, i);
break;
}
if (all) {
c--;
break;
}
fronta::Enqueue(phead, ptail, 0);
visited[0] = true;
while (!fronta::IsQueueEmpty(phead)) {
v = fronta::Dequeue(phead, ptail);
//cout << "processing vertex: " << v << endl;
for (int j = 0; j < n; j++) {
if (gr3[v][j] && !visited[j]) {
fronta::Enqueue(phead, ptail, j);
visited[j] = true;
}
}
}
}
But it doesn't work very well...

Receiving updated value from recursive call

I have a DFS function which collects entry and leave times of vertices. Unfortunately, I am unable to receive a proper value for leave time, because it is not connected with the value from recursive call.
void DFS_visit(int i, vector<int> Adj[], int visited[], int p[], int entry[], int leave[], int t)
{
visited[i] = 1;
entry[i] = t;
cout << i << " ";
for (auto u : Adj[i])
{
if (!visited[u])
{
p[u] = i;
DFS_visit(u, Adj, visited, p, entry, leave, t++);
}
}
leave[i] = t++;
}
It is obviously an auxiliary function, I also have a "main" DFS function:
void DFS(vector<int> Adj[], int n)
{
int visited[n], p[n], entry[n], leave[n];
int t = 0;
for (int i = 0; i < n; i++)
{
visited[i] = 0;
p[i] = -1;
}
for (int i = 0; i < n; i++)
{
if (!visited[i])
{
DFS_visit(i, Adj, visited, p, entry, leave, t);
}
}
Could you please tell me how I am supposed to pass the updated value of leave time to leave[i]? Thanks in advance!

Count number of nodes in each connected part of an undirected unweighted graph

I am new to C++ STL and have started Graph Theory recently.
After referring to https://www.geeksforgeeks.org/connected-components-in-an-undirected-graph/, I can count the number of connected components in an undirected, unweighted graph using DFS as:
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
int connected=0, temp1, temp2,n, p;
void DFS(int start, vector<int> v[],vector<int> &visited) {
visited[start] = 1;
for(int i= 0; i<v[start].size(); ++i) {
if(visited[v[start][i]] == 0)
DFS(v[start][i], v, visited);
}
}
int main() {
cin>>n>>p; // number of vertices and edges
vector<int> v[n+1], visited(n+1,0);
for(int i=0; i<p; ++i) {
cin>>temp1>>temp2;
v[temp1].push_back(temp2);
v[temp2].push_back(temp1);
}
connected = 0;
for(int i=1;i<=n;++i) {
if(visited[i] == 0 ) {
connected++;
DFS(i,v,visited);
}
}
cout<<connected<<endl;
return 0;
}
But how do we count the total number of nodes in each component?
For example: In this graph, see image there are 3 connected
components, with no. of nodes being 3, 2 , and 1 respectively.
You could maintain a dummy variable count with each call to DFS from main()
void DFS(int start, vector<int> v[],vector<int> &visited, int &count)
{
visited[start] = 1;
count++;
for(int i= 0; i<v[start].size(); ++i)
{
if(visited[v[start][i]] == 0)
DFS(v[start][i], v, visited);
}
}
and
for(int i=1;i<=n;++i)
{
if(visited[i] == 0 )
{
connected++;
int count=0;
DFS(i,v,visited,count);
cout<<"This component has "<<count<<" nodes"<<"\n";
}
}
Or you could refer to the change in visited vector(number of new 1's in it) after every call to DFS() from main()
you can maintain a global variable no_of_nodes which will be set to zero at start of dfs of each component and incremented by one when you visit each node in that component.
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
int connected=0, temp1, temp2,n, p;
int no_of_nodes=0;
void DFS(int start, vector<int> v[],vector<int> &visited) {
visited[start] = 1;
no_of_nodes++;
for(int i= 0; i<v[start].size(); ++i) {
if(visited[v[start][i]] == 0)
DFS(v[start][i], v, visited);
}
}
int main() {
cin>>n>>p; // number of vertices and edges
vector<int> v[n+1], visited(n+1,0);
for(int i=0; i<p; ++i) {
cin>>temp1>>temp2;
v[temp1].push_back(temp2);
v[temp2].push_back(temp1);
}
connected = 0;
vector<int>nodes;
for(int i=1;i<=n;++i) {
if(visited[i] == 0 ) {
connected++;
no_of_nodes=0;
DFS(i,v,visited);
nodes.push_back(no_of_nodes);
}
}
cout<<connected<<endl;
return 0;
}

How to find of what vertices is made cycle in undirected graph if there is only one cycle in graph?

how to find of what vertices is made cycle in undirected graph if there is only one cycle in graph?
I have code for finding cycle in graph, but right now I need code that will find of what vertices cycle is made.
Here is code(in C++) for finding cycle:
bool dfs(int x)
{
state[x] = 1;
for(int j = 0; j < ls[x].size(); j++)
{
if(state[ls[x][j]] == 1 and parent[x] != ls[x][j])
{
t = 0; // Graph contains cycle.
return t;
}
if(state[ls[x][j]] == 0)
{
parent[ls[x][j]] = x;
dfs(ls[x][j]);
}
}
}
void detect_cycle()
{
memset(state, 0, sizeof state);
memset(parent, 0, sizeof parent);
for(int i = 1; i <= n; i++)
if(state[i] == false)
dfs(i);
}
Thanks.
Here is the final code. Thanks guys.
bool dfs(int x)
{
state[x] = 1;
for(int j = 0; j < ls[x].size(); j++)
{
if(state[ls[x][j]] == 1 and parent[x] != ls[x][j])
{
if(t)
{
printf("Cycle entry: %d\n", ls[x][j]);
printf("Cycle contains: %d, %d ", ls[x][j], x);
int cycleNode = parent[x];
while(cycleNode != ls[x][j])
{
printf("%d ", cycleNode);
cycleNode = parent[cycleNode];
}
}
t = 0;
return t;
}
if(state[ls[x][j]] == 0)
{
parent[ls[x][j]] = x;
dfs(ls[x][j]);
}
}
}
A naive method - just throw away any node with degree 1, until all nodes have degree 2. This is the cycle in the graph.
If i'm right, then parent[] is an array (parent[i] is the number of the node that you vivted straight before you visited the i-th one).
Then you know that if the graph contains the cycle (you visit a node you have already visited), you know at least one node in the cycle (suppose its the k-th one). In this case, the parent[k] node also belongs to the cycle, and parent[parent[k]], and so on.
So, we get the next code:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <set>
#include <map>
using namespace std;
vector <int> state;
vector <vector <int> > ls; //graph
vector <int> parent;
bool t = 1;
int theNodeInTheCycle;
void dfs(int x)
{
state[x] = 1;
for(int j = 0; j < ls[x].size(); j++)
{
if(state[ls[x][j]] == 1 && parent[x] != ls[x][j])
{
parent[ls[x][j]] = x;
theNodeInTheCycle = ls[x][j]; //ls[x][j] belongs to the cycle since state[ls[x][j]]==1
t = 0;
}
if(state[ls[x][j]] == 0)
{
parent[ls[x][j]] = x;
dfs(ls[x][j]);
}
}
}
vector <int> GetCycle ()
{
vector <int> cycle;
int firstNodeInTheCycle = theNodeInTheCycle;
do
{
theNodeInTheCycle = parent[theNodeInTheCycle];
cycle.push_back (theNodeInTheCycle);
} while (theNodeInTheCycle != firstNodeInTheCycle);
reverse (cycle.begin (), cycle.end ()); //to get them in the right order
return cycle;
}
int main()
{
int n; cin>>n; //the number of nodes (from 0 to n-1)
int m; cin>>m; //the number of edges
state.resize (n);
ls.resize (n);
parent.resize (n);
for (int i = 0; i < m; ++i)
{
int a, b; cin>>a>>b;
ls[a].push_back(b);
ls[b].push_back(a);
}
for (int i = 0; i<n; ++i)
if (state[i]==0)
dfs(i);
if (t==0)
{
vector <int> cycle = GetCycle ();
for (int i = 0; i < cycle.size (); ++i)
cout<<cycle[i]<<" ";
cout<<"\n";
}
else cout<<"No cycle\n";
}
when you run dfs, if a vertex is marked when dfs() before, there must be a cycle.
A
/
B
| \
C E
\ /
D
if there is only one cycle in graph, the vertex marked before is the entry of cycle, as B below, whatever the start vertex of dfs is.
and in your code,
if(state[ls[x][j]] == 1 and parent[x] != ls[x][j])
{
t = 0; // Graph contains cycle.
return t;
}
in the first if() {},parent and t is unnecessary,change to:
if(state[ls[x][j]] == 1 and parent[x] != ls[x][j])
{
cout<<"cycle's entry:"<<j<<endl;
// Graph contains cycle.
return false;
}
besides,your code need a return true; outside the for of dfs().