Notes on bfs and dfs

Posted by seanlim on Fri, 31 Dec 2021 22:28:44 +0100

See a problem, the problem solution summarizes the bfs and dfs templates to record.  

1: bfs

bfs is accessed layer by layer, which is suitable for finding the shortest path steps with goals. Think about searching layer by layer, and each layer represents one step. bfs gives priority to sibling nodes (adjacent nodes). Only when this layer is fully accessed can it access the next layer, that is, the bfs layer represents the current location (node)

2: dfs


DFS is implemented by recursion. It gives priority to searching depth and then backtracking. Priority access is given to child nodes that have not been accessed. DFS is mostly used for connectivity problems. Because its operation idea is very similar to that of human brain, it is more natural to solve connectivity problems.

    

The following is a simple framework for bfs and dfs

1: bfs

Template:

First://bfs template
struct ed
{
	.....
}
deque<ed>q;//Of course, you can also use queue
void bfs()
{
	Mark start point 
	Start in queue 
	while(!q.empty())//Queue is not empty 
	{
		ed nw=q.front();//Return to the head of the team
		for(Expand the next possible state)
		{
			ed nxt;
			Record this status
			Judge whether the status is legal 
			Tag status 
			q.push_back(nxt);//Status queued 
		}
		q.pop_front();//Pop up team leader 
	}
}


Second:
/** 
 * Breadth first search 
 * @param Vs starting point 
 * @param Vd End 
 */  
bool BFS(Node& Vs, Node& Vd){  
    queue<Node> Q;  
    Node Vn, Vw;  
    int i;  

    //The initial state puts the starting point into the queue Q  
    Q.push(Vs);  
    hash(Vw) = true;//The setting node has been accessed!  

    while (!Q.empty()){//The queue is not empty, continue searching!  
        //Take out the header Vn of the queue  
        Vn = Q.front();  

        //Remove from queue  
        Q.pop();  

        while(Vw = Vn A node that can be reached by a rule){  
            if (Vw == Vd){//Found the end!  
                //Record the path. There is no solution here  
                return true;//return  
            }  

            if (isValid(Vw) && !visit[Vw]){  
                //Vw is a legal node and is a white node  
                Q.push(Vw);//Join queue Q  
                hash(Vw) = true;//Set node color  
            }  
        }  
    }  
    return false;//unsolvable  
}  

2: dfs

Template:

First://It is also a time to go to the end, and then go back
void dfs()
{
	for(Expansion state)
	{
		Legal judgment
		record
		dfs(Keep searching);
		to flash back;
	}
}
*/

Second:
void dfs(){
    Search whether the upper, lower, left and right positions meet the conditions.
    if((qualified) {
        sign
        dfs()
    }
}

Record a question according to the template for easy understanding

Title:

A rectangular array is composed of numbers ^ 00 ^ 99 ^ and numbers ^ 11 ^ 99 ^ represent cells. The definition of cells is up, down, left and right along the cell number. If it is still a cell number, it is the same cell. Calculate the number of cells of a given rectangular array.

Input format

The two integers in the first row represent the matrix sizes {nn} and {mm.

Next, a string containing only characters ¢ 0 ¢ to ¢ 9 ¢ with a length of ¢ mm , represents the ¢ n \times mn × The matrix of m.

Output format

An integer in a row represents the number of cells.

Input and output samples

Enter #1

4 10
0234500067
1034560500
2045600671
0000000089

Output #1

In fact, the idea is very simple. In order to facilitate understanding, I specially marked the number 0 in red. It was found that there are only four connected blocks wrapped by the number 0.

The first is the solution of bfs:

#include<iostream>
#Include < deque > / / bidirectional queue header file
using namespace std;
struct pp
{
	int x, y;
};//Initialization function
deque<pp> q;//queue
int n, m, ans = 0;//n rows, m columns, ans is the answer 
int a[105][105];//Storage matrix 
bool used[105][105];//Record whether you have passed 
int dx[4] = { -1,1,0,0 };//Take a step up, down, left and right, line number and list the changes 
int dy[4] = { 0,0,-1,1 };
void bfs(int sx, int sy)//bfs 
{
	pp st;
	st.x = sx; st.y = sy;
	used[sx][sy] = 1;
	q.push_back(st);
	while (!q.empty())
	{
		pp nw = q.front();
		for (int i = 0; i < 4; i++)
		{
			pp nxt = nw;
			nxt.x += dx[i];
			nxt.y += dy[i];
			if (a[nxt.x][nxt.y] == 0 || used[nxt.x][nxt.y] == 1) continue;//If it's zero, don't worry about him
			used[nxt.x][nxt.y] = 1;//Dye the dots of this connecting block 
			q.push_back(nxt);
		}
		q.pop_front();//Because it's a two-way queue. This allows the traversed number to go out
	}
}
int main()
{
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++)
			scanf("%1d", &a[i][j]);//Traverse map
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= m; j++)
		{
			if (used[i][j] == 0 && a[i][j] != 0)
			{
				bfs(i, j);
				ans++;//If you haven't searched ans in this connection++ 
			}
		}
	}
	cout << ans;
	return 0;
}

Secondly, the dfs method, because they are connected blocks, the difference is not too large

#include<iostream>
using namespace std;
int n, m, ans = 0;
int a[105][105];
bool used[105][105];
int dx[4] = { -1,1,0,0 };
int dy[4] = { 0,0,-1,1 };
void dfs(int x, int y)
{
	used[x][y] = 1;
	for (int i = 0; i < 4; i++)
	{
		int nx = x + dx[i];
		int ny = y + dy[i];
		if (a[nx][ny] == 0 || used[nx][ny] == 1) continue;
		dfs(nx, ny);//to flash back
	}
}
int main()
{
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= m; j++)
			scanf("%1d", &a[i][j]);//Traverse map
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= m; j++)
		{
			if (used[i][j] == 0 && a[i][j] != 0)
			{
				dfs(i, j);
				ans++;//Find connected blocks
			}
		}
	}
	cout << ans;
	return 0;
}

in short

One focuses on queues, the other on backtracking, well, that's it.

Topics: C++