Finding the cycle in an undirected graph using BFS - graph

I want to find first cycle in an undirected graph using BFS only(NOT DFS). All sources solved this problem with DFS but I have to find it using BFS. How can I find it? Thanks in advance!

Here below you will find the code to traverse a graph using BFS and find its cycles.
#include <stdio.h>
#include <queue>
using namespace std;
int nodes, edges, src;
int graph[100][100], color[100], prev[100];
const int WHITE = 0;
const int GRAY = 1;
const int BLACK = 2;
void print(int);
int main() {
printf("Nodes, edges, source? ");
scanf("%d %d %d ", &nodes, &edges, &src);
for(int i = 1; i <= edges; i++) {
printf("Edge %d: ", i);
int x, y;
scanf("%d %d", &x, &y);
graph[x][y] = 1;
}
//run BFS
queue<int> q; //create a queue
q.push(src); //1. put root node on the queue
do{
int u = q.front(); //2. pull a node from the beginning of the queue
q.pop();
printf("%d ", u); //print the node
for(int i = 1; i <= nodes; i++) { //4. get all the adjacent nodes
if((graph[u][i] == 1) //if an edge exists between these two nodes,
&& (color[i] == WHITE)) { //and this adjacent node is still WHITE,
q.push(i); //4. push this node into the queue
color[i] = GRAY; //color this adjacent node with GRAY
}
}
color[u] = BLACK; //color the current node black to mark it as dequeued
} while(!q.empty()); //5. if the queue is empty, then all the nodes havebeen visited
//find and print cycle from source
for(int i = 1; i <= nodes; i++) {
if(graph[i][src] == 1) {
print(i);
printf("%d\n\n", src);
}
}
return 0;
}
void print(int node) {
if(node == 0)
return;
print(prev[node]);
printf("%d -> ", node);
}
Also I recommend you to take a look at this brief and useful guide.

Related

When finding cycles in undirected graphs, why can't we just keep track of previous parent node while using BFS traversal

Basically when we use DFS we just check if the adjacent nodes for a newly visited node have been already visited and they are not the parent node which made the DFS call for this node. If this is the case cycle is present.
I was using similar thing for BFS while keeping track of previous parent node and my logic doesn't seem to work. The test case on which my code is failing is too big to understand the problem. Can anyone let me know where my logic is broken? Thank you in advance
bool bfs(vector<int> adj[], bool isVisited[], int s, int V)
{
queue<int> q;
q.push(s);
isVisited[s] = true;
int parent = s;
int prevParent = -1;
while(q.empty() == false)
{
int u = q.front();
prevParent = parent;
parent = u;
q.pop();
for(int i = 0 ; i < adj[u].size() ; i++)
{
if(isVisited[adj[u][i]] == false)
{
isVisited[adj[u][i]] = true;
q.push(adj[u][i]);
// parent[][i]] = u;
}
else
{
if(adj[u][i] != prevParent)
return true;
}
}
}
return false;
}
bool isCycle(int V, vector<int> adj[]) {
// Code here
bool isVisited[V] = {false};
for(int i = 0 ; i < V ; i++)
{
if(isVisited[i] == false)
if(bfs(adj, isVisited, i, V) == true)
{
return true;
}
}
return false;
}

find the longest distance whit DFS

i have this implementation of DFS:
void Graph::DFS(int start, vector<bool>& visited){
// Print the current node
cout << start << " ";
// Set current node as visited
visited[start] = true;
// For every node of the graph
for (int i = 0; i < v; i++) {
// If some node is adjacent to the current node
// and it has not already been visited
if (adj[start][i] == 1 && (!visited[i])) {
DFS(i, visited);
}
}
Instead of printing the travel i want it return the longest disntance from this start vertex.
what can i change into the code?
With a few changes you are able to do it, but it will be very slow.
int Graph::DFS(int start, vector<bool>& visited){
// Set current node as visited
visited[start] = true;
int out = 0;
// For every node of the graph
for (int i = 0; i < v; i++) {
// If some node is adjacent to the current node
// and it has not already been visited
if (adj[start][i] == 1 && (!visited[i])) {
out = max(out, DFS(i, visited) + 1);
}
}
visited[start] = false;
return out;

Tree returning the maximum value

50
/ \
30 70 (( which should return 50+70=120 ))
int MyFunction(struct node *root){
struct node *ptr=root;
int leftsum=0;
int rightsum=0;
if(ptr==NULL){
return;
}
else{
MyFunction(ptr->left);
leftsum=leftsum+ptr->key;
MyFunctipn(ptr->right);
rightsum=rightsum+ptr->key;
return (root->key+max(leftsum,rightsum));
}
}
for that, I've written this code. Maybe it is wrong so please help me as I'm new in this field. I want to write a recursive code such a way that it compares two leaf node(left and right) and returns the maximum to the parent nood.
The recursive function should look something like this:
int getMaxPath(Node* root){
// base case, We traveled beyond a leaf
if(root == NULL){
// 0 doesn't contribute anything to our answer
return 0;
}
// get the max current nodes left and right children
int lsum = getMaxPath(root->left);
int rsum = getMaxPath(root->right);
// return sum of current node value and the maximum from two paths starting with its two child nodes
return root->value + std::max(lsum,rsum);
}
Full code:
#include <iostream>
struct Node{
int value;
Node* left;
Node* right;
Node(int val){
value = val;
left = NULL;
right = NULL;
}
};
// make a tree and return a pointer to it's root
Node* buildTree1(){
/* Build tree like this:
50
/ \
30 70
*/
Node* root= new Node(50);
root->left = new Node(30);
root->right = new Node(70);
}
int getMaxPath(Node* root){
if(root == NULL){
// 0 doesn't contribute anything to our answer
return 0;
}
int lsum = getMaxPath(root->left);
int rsum = getMaxPath(root->right);
return root->value + std::max(lsum,rsum);
}
int main() {
using namespace std;
Node* root = buildTree1();
int ans = getMaxPath(root);
cout<< ans <<endl;
return 0;
}
int Sum(struct node *root)
{
if(root->left == NULL && root->right== NULL)
return root->key;
int lvalue,rvalue;
lvalue=Sum(root->left);
rvalue=Sum(root->right);
return root->key+max(lvalue,rvalue);
}
int max(int r,int j)
{
if(r>j)
return r;
else
return j;
}

Bridges in an Undirected Graph

A bridge can only exist between two articulation points or between an articulation point and a node with degree 1.
This is just an observation because if a vertex is articulation point then simply disconnecting from that node will give us bridges only.
Please tell me if this is true or false.
/*A sample file should contain edges as follow
1,2
2,3
4,5
5,3
Output will give the set of bridge nodes
*/
#include<stdio.h>
#include<stdlib.h>
#define MAX 100
typedef struct graph
{
int node;
struct graph *next;
}graph;
void init(int group[],int index[],graph *g[]);
void create_graph(graph *g[],int node1,int node2,int group[],int index[],int max_nodes);
int max(int a,int b);
int min(int a,int b);
void display(graph *g[],int group[],int max_nodes);
int query(graph *g[],int group[],int max_nodes,int first,int second);
void delete_node(graph *g[],int node1,int node2,int group[],int index[],int max_nodes);
int team=0;
int main()
{
char filename[50],ch;
int nodes[MAX][2],temp=0,node1,node2,group[MAX],index[MAX],max_nodes=0,i;
FILE *fp;
graph *g[MAX],*p;
init(group,index,g);
printf("Enter the filename - ");
scanf("%s",filename);
fp=fopen(filename,"r");
if(fp==NULL)
{
printf("File does not exist");
exit(1);
}
while(1)
{
ch=fgetc(fp);
if(isdigit(ch))
temp=temp*10+(ch-48);
else
{
if(ch!=','&&ch!='\n'&&ch!=EOF)
exit(1);
if(ch==',')
node1=temp;
else
{
node2=temp;
if(node1>max_nodes)
max_nodes=node1;
if(node2>max_nodes)
max_nodes=node2;
if(node1!=node2&&node1>0&&node2>0)
create_graph(g,node1,node2,group,index,max_nodes);
}
temp=0;
}
if(ch==EOF)
{
break;
}
}
display(g,group,max_nodes);
temp=0;
fclose(fp);
fp=fopen(filename,"r");
printf("Set of bridges existing - \n\n");
while(1)
{
ch=fgetc(fp);
if(isdigit(ch))
temp=temp*10+(ch-48);
else
{
if(ch!=','&&ch!='\n'&&ch!=EOF)
exit(1);
if(ch==',')
node1=temp;
else
{
node2=temp;
if(node1>max_nodes)
max_nodes=node1;
if(node2>max_nodes)
max_nodes=node2;
if(node1!=node2&&node1>0&&node2>0)
delete_node(g,node1,node2,group,index,max_nodes);
}
temp=0;
}
if(ch==EOF)
{
break;
}
}
return 0;
}
void init(int group[],int index[],graph *g[])
{
int i;
graph *p=NULL;
for(i=0;i<MAX;i++)
{
group[i]=index[i]=0;
g[i]=(graph *)malloc(sizeof(graph));
g[i]->node=0;
g[i]->next=NULL;
}
}
void create_graph(graph *g[],int node1,int node2,int group[],int index[],int max_nodes)
{
int temp_index,other_index,i,minimum;
int stack[MAX],stack_index=0;
graph *p;
p=g[node1];
if(p->next)
{
p=p->next;
while(p)
{
if(p->node==node2)
return;
p=p->next;
}
}
if(g[node1]->node<g[node2]->node)
{
temp_index=node1;
other_index=node2;
}
else
{
temp_index=node2;
other_index=node1;
}
p=g[temp_index];
p->node=p->node+1;
while(p->next!=NULL)
p=p->next;
p->next=(graph *)malloc(sizeof(graph));
p=p->next;
p->node=other_index;
p->next=NULL;
p=g[other_index];
p->node=p->node+1;
while(p->next)
p=p->next;
p->next=(graph *)malloc(sizeof(graph));
p=p->next;
p->node=temp_index;
p->next=NULL;
if(group[temp_index]==group[other_index]&&group[temp_index]==0)
{
{
team++;
group[temp_index]=group[other_index]=team;
}
}
else
{
if(group[temp_index]==0)
{
group[temp_index]=group[other_index];
}
{
minimum=min(group[temp_index],group[other_index]);
group[temp_index]=max(group[temp_index],group[other_index]);
for(i=1;i<=max_nodes;i++)
{
if(group[i]==minimum)
group[i]=max(group[temp_index],group[other_index]);
}
}
}
}
int max(int a,int b)
{
if(a>b)
return a;
return b;
}
int min(int a,int b)
{
if(a<b)
return a;
return b;
}
void display(graph *g[],int group[],int max_nodes)
{
int i;
graph *p;
printf("Graph\n");
printf("Id\tGrp\tNodes\n");
for(i=1;i<=max_nodes;i++)
{
printf("%d\t%d\t%d",i,group[i],g[i]->node);
p=g[i]->next;
while(p)
{
printf(" %d",p->node);
p=p->next;
}
printf("\n");
}
printf("\n\n");
}
int query(graph *g[],int group[],int max_nodes,int first,int second)
{
if(group[first]==group[second])
return 1;
else
return 0;
}
void delete_node(graph *g[],int node1,int node2,int group[],int index[],int max_nodes)
{
graph *p=NULL;
int i,temp,stack_index=0,stack[MAX];
p=g[node1];
while(p->next->node!=node2&&p->next)
p=p->next;
if(p->next)
{
p->next=p->next->next;
g[node1]->node=g[node1]->node-1;
}
p=g[node2];
while(p->next->node!=node1&&p->next)
p=p->next;
if(p->next)
{
p->next=p->next->next;
g[node2]->node=g[node2]->node-1;
}
team++;
group[node2]=team;
stack_index=0;
temp=node2;
p=g[temp]->next;
while(p)
{
stack[stack_index++]=p->node;
p=p->next;
}
for(i=0;i<stack_index;i++)
{
if(group[stack[i]]!=team)
{
group[stack[i]]=team;
p=g[stack[i]]->next;
while(p)
{
stack[stack_index++]=p->node;
p=p->next;
}
}
}
if(query(g,group,max_nodes,node1,node2)==0)
printf("%d %d\n",node1,node2);
create_graph(g,node1,node2,group,index,max_nodes);
}
In an undirected graph, a bridge can only exist between two articulation points. That goes straight from the definitions:
Bridge is an edge, such that removing it from the graph increases the number of connected components.
If you remove any of its endpoints, you therefore increase the number of connected components as well, and that's exactly the definition of articulation point.
I'm not sure what you mean with the part or between an articulation point and a node with out-degree 0. What would out-degree mean in an undirected graph?
Here are nice slides on Tarjan's algorithm, including its usage for detecting bridges and articulation points in graphs.
"The key issue is determining how the reachability relation impacts whether
vertex v is an articulation vertex. There are three cases:
• Root cut-nodes – If the root of the DFS tree has two or more children, it must
be an articulation vertex. No edges from the subtree of the second child can
possibly connect to the subtree of the first child.
• Bridge cut-nodes – If the earliest reachable vertex from v is v, then deleting
the single edge (parent[v], v) disconnects the graph. Clearly parent[v] must
be an articulation vertex, since it cuts v from the graph. Vertex v is also an
articulation vertex unless it is a leaf of the DFS tree. For any leaf, nothing
falls off when you cut it.
• Parent cut-nodes – If the earliest reachable vertex from v is the parent of v,
then deleting the parent must sever v from the tree unless the parent is the
root." - The algorithm design manual by Steve Skiena

Why does the x value change in this program?

I have created this code, and when I run it, don't get any errors until the arrow leaves the screen (ie: (*I)->x>maxx), after which the O will randomly teleport (Well, I'm guessing its not random, but I'm trying to find a pattern to it).
EDIT: the random teleportation don't seem to occur if I move up, and if I move down, the O is teleported directly to the bottom. Also, a glitch has occured where the O becomes a '>'. (I am trying to figure out how that happens)
EDIT: the transform-into-'>' glitch occurs if the O is at the bottom right of the screen (player.x=9;player.y=9) and the sequence "wqs" is entered.
EDIT: I've removed the class declarations because I am fairly sure that the error is within the _move()s and check().
EDIT: The transform glitch appears to occur when 'wq' is typed, then any other character is entered (ie "skiping" the next move)
EDIT: The tranform glitch occurs when player.x=9; player.y=8; and then 'q' is pressed, the next move the player tranforms into a '>'
This is the code:
#include<vector>
#include<iostream>
#include<string>
using namespace std;
const int maxx = 10, maxy = 10; //two constants that show the size of the sector
char sector[maxx][maxy]; //array of characters used to display the sector
prgm player(0, 0, 'O'); //player definition at x0,y0,and displayed with 'O'
const int vsize = 1; //size of the enemy array (ie: how many enemies there will be
X1 a(9, 5, 'X', 10); //enemy "a", has a move function that moves it back and forth
virus * viral_data[vsize] = {&a}; //array of enemies used to set the sector
vector<antivirus*> antiviral_data; //vector of pointers to "antivirus" the weapon used
vector<antivirus*>::iterator I; //iterator for previous vector
void display() //function to display the sector
{
for(int i = 0; i < maxy; i++)
{
for(int j = 0; j < maxx; j++)
{
cout<<sector[j][i];
}
cout<<endl;
}
return;
}
void p_move() //function to get players input, then move the player or create "antivirus"
{
char dir;
cin>>dir;
switch(dir)
{
case 'w':
player.y--;
break;
case 'a':
player.x--;
break;
case 's':
player.y++;
break;
case 'd':
player.x++;
break;
case 'q':
antiviral_data.push_back(new aX1(player.x, player.y, '>')); //creates a new aX1 at the players position
break;
}
return;
}
void v_move() //uses the enemies move
{
for(int i = 0; i < vsize; i++)
{
viral_data[i]->move();
}
return;
}
void a_move() //uses the weapon (ie: moves the weapon forward)
{
for(I = antiviral_data.begin(); I < antiviral_data.end(); I++)
{
(*I)->move();
}
return;
}
void set() //sets the sector array (char)
{
for(int i = 0; i < maxy; i++)
{
for(int j = 0; j < maxx; j++)
{
sector[j][i] = ' '; makes the entire sector blank
}
}
sector[player.x][player.y]=player.sym; //sets the sector at the player's position to 'O'
for(int i = 0; i < vsize; i++)
{
sector[viral_data[i]->x][viral_data[i]->y] = viral_data[i]->sym; //sets the sector at each enemy's position to be 'X'
}
for(I = antiviral_data.begin(); I < antiviral_data.end(); I++)
{
sector[(*I)->x][(*I)->y] = (*I)->sym; //sets the sector at each weapon's position to be '>'
}
return;
}
void check() //prevents the player from moving off the screen, erases bullet if it moves of the screen (to prevent access to non-allocated memory)
{
if(player.x < 0)
{
player.x = 0;
}
if(player.y < 0)
{
player.y = 0;
}
if(player.x > (maxx-1))
{
player.x = (maxx-1);
}
if(player.y > (maxy-1))
{
player.y = (maxy-1);
}
//PROBLEM APPEARS TO OCCUR HERE
for(I = antiviral_data.begin(); I! = antiviral_data.end();)
{
if((*I)->x > maxx)
{
I = antiviral_data.erase(I);
}
else
{
I++;
}
}
//*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
return;
}
int main()
{
while(true)
{
set(); //set sector
display(); //display sector
p_move(); //player's move
v_move(); //enemy's move
a_move(); //bullet's move
check();//check moves
}
return 0;
}
In check(), the test
((*I)->x > maxx)
should be
((*I)->x >= maxx)
. This is an off-by-one error that lets the > get one square off the screen. When the display routine tries to display it, it clobbers the display symbol for the X.

Resources