使用DFS求连通块

注意使用DFS求连通块因为递归调用函数,只能用于不大的数据,数据过大会递归爆栈!


1.输入一个N*M的字符矩阵,统计其中‘@’共组成多少个连通块(N与M不超过100)

#include<iostream>
#include<cstring>
using namespace std;
int n, m, vis[101][101];                                     //vis数组记录该点所在连通块的序号,不在则为零
char map[101][101];
int dx[4] = { 1,0,-1,0 }, dy[4] = { 0,1,0,-1 };
int num = 0;
void dfs(int x, int y,int num)
{
	if (x >=n || x<0 || y>=m || y < 0||vis[x][y]>0||map[x][y]!='@')  return;
		vis[x][y] = num;                             //给该连通块标记序号
		for (int i = 0; i < 4; i++)                  //四个方向DFS递归
			dfs(x + dx[i], y + dy[i], num);
}
int main()
{
	cin >> n >> m;
	for (int i = 0; i < n; i++)
		for (int j = 0; j < m; j++)
			cin >> map[i][j];
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < m; j++)
			if (map[i][j] == '@'&&vis[i][j] == 0)
			{
				num++;
				dfs(i, j, num);
			}
	}
	cout << num << endl;
	return 0;
}


2.输入一个N*M的字符矩阵,输入一个坐标,若该坐标在连通块中则输出该连通块有多少格(N与M不超过100)

#include<iostream>
#include<cstring>
using namespace std;
int n, m, vis[101][101];
char map[101][101];
int dx[4] = { 1,0,-1,0 }, dy[4] = { 0,1,0,-1 };
int num = 0, res[10001], sum = 1;                              //增加res数组每块连通块的个数
void dfs(int x, int y,int num)
{
	if (x >n || x<1 || y>m || y < 1||vis[x][y]>0||map[x][y]!='@')  return;
		vis[x][y] = num;
		sum++;                                        //计数器自增统计个数
		for (int i = 0; i < 4; i++)
			dfs(x + dx[i], y + dy[i], num);
}
int main()
{
	cin >> n >> m;
	for (int i = 1; i <=n; i++)
		for (int j = 1; j <= m; j++)
			cin >> map[i][j];
	for (int i = 1; i <=n; i++)
	{
		for (int j = 1; j <=m; j++)
			if (map[i][j] == '@'&&vis[i][j] == 0)
			{
				sum = 0;
				num++;
				dfs(i, j, num);
				res[num] = sum;
			}
	}
	int p1, p2;
	cin >> p1 >> p2;
	if (vis[p1][p2] != 0)
		cout << res[vis[p1][p2]] << endl;
	else
		cout << "该点不在连通块中!" << endl;
	return 0;}

典型例题:颜色填涂

由数字 00 组成的方阵中,有一任意形状闭合圈,闭合圈由数字 11 构成,围圈时只走上下左右 44 个方向。现要求把闭合圈内的所有空间都填写成 22 .例如: 6 \times 66×6 的方阵( n=6n=6 ),涂色前和涂色后的方阵如下:

0 0 0 0 0 0
0 0 1 1 1 1
0 1 1 0 0 1
1 1 0 0 0 1
1 0 0 0 0 1
1 1 1 1 1 1
0 0 0 0 0 0
0 0 1 1 1 1
0 1 1 2 2 1
1 1 2 2 2 1
1 2 2 2 2 1
1 1 1 1 1 1
输入格式:

每组测试数据第一行一个整数 

n(1 \le n \le 30)n(1n30)

接下来 nn 行,由 00 和 11 组成的 n \times nn×n 的方阵。

方阵内只有一个闭合圈,圈内至少有一个 00 。

#include<iostream>
using namespace std;
int n,  map[31][31];
int vis[31][31];
int dx[4] = { 1,0,-1,0 }, dy[4] = { 0,1,0,-1 };
void dfs(int x, int y)
{
	if (x > n || x<1 || y>n || y < 1 || vis[x][y]>0 || map[x][y] != 0)  return;
	vis[x][y] = 1;
	for (int i = 0; i < 4; i++)
	{
		dfs(x + dx[i], y + dy[i]);
	}
}
int main()
{
	cin >> n;
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= n; j++)
		{
			cin >> map[i][j];
			if (map[i][j] == 1)
				vis[i][j] = 2;
		}
	}
	for (int i = 1, j = 1; j <= n; j++)
		if (vis[i][j] == 0 && map[i][j] == 0)
			dfs(i, j);
	for (int i = n, j = 1; j <= n; j++)
		if (vis[i][j] == 0 && map[i][j] == 0)
			dfs(i, j);
	for (int j = 1, i = 1; i <= n;i++)
		if (vis[i][j] == 0 && map[i][j] == 0)
			dfs(i, j);
	for (int j = n, i = 1; i <= n; i++)
		if (vis[i][j] == 0 && map[i][j] == 0)
			dfs(i, j);
	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= n; j++)
		{
			if (vis[i][j] == 1)
				cout << '0'<<' ';
			if (vis[i][j] == 2)
				cout << '1'<<' ';
			if (vis[i][j] == 0)
				cout << '2'<<' ';
		}
		cout << endl;
	}
	return 0;
}







猜你喜欢

转载自blog.csdn.net/slience_646898/article/details/80964151
今日推荐