为什么标记连通块不能只搜两个方向呢?
  • 板块P1141 01迷宫
  • 楼主zclll
  • 当前回复2
  • 已保存回复2
  • 发布时间2021/7/20 12:25
  • 上次更新2023/11/4 14:04:46
查看原帖
为什么标记连通块不能只搜两个方向呢?
500070
zclll楼主2021/7/20 12:25

一开始我的代码如下:

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;

#define N 1003
int n, m;
int arr[N][N];
typedef pair<int, int> P;
#define mp(x, y) make_pair(x, y)
int bl[N][N];
int l;
int siz[N * N];
bool vis[N][N];
int d[][2] = {{1,0},{0,1}};
void bfs(int x, int y, int block)
{
	queue<P> que;
	que.push(mp(x, y));
	bl[x][y] = block;
	vis[x][y] = true;
	while (!que.empty())
	{
		auto now = que.front();
		que.pop();
		for (int i = 0; i <= 1; i ++)
			{
				int newx = now.first + d[i][0];
				int newy = now.second + d[i][1];
				if (newx >= 1 && newx <= n && newy >= 1 && newy <= n
				&& !vis[newx][newy] && arr[newx][newy] != arr[now.first][now.second])
				{
					bl[newx][newy] = block;
					vis[newx][newy] = true;
					que.push(mp(newx, newy));
				}
			}
	}
}
int main()
{
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
		{
			char ch;
			scanf(" %c", &ch);
			arr[i][j] = ch - '0';
		}
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
			if (!bl[i][j])
			{
				bfs(i, j, ++l);
				siz[l]++;
			}
			else
				siz[bl[i][j]]++;
	while (m--)
	{
		int x, y;
		cin >> x >> y;
		cout << siz[bl[x][y]] << endl;
	}
	return 0;
}

这里我只搜了向右和向下的方向。因为按照55、56行的循环顺序,任意当前点的左侧/上侧点一定已经被访问过,如果当前点v和某左侧/上侧点x处于同一个连通块,那么bfs(x)的时候一定已经访问过v了,所以只要!bl[i][j]就意味着当前点所属的连通块不可能拓展到左侧/上侧。

然而代码无情的蛙了。于是我将2连通改成了4连通,过了。

说明我以上推理是错误的,请问我的错误在哪里?求大佬指教

AC代码(只改动了20、31行):

#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;

#define N 1003
int n, m;
int arr[N][N];
typedef pair<int, int> P;
#define mp(x, y) make_pair(x, y)
int bl[N][N];
int l;
int siz[N * N];
bool vis[N][N];
int d[][2] = {{1,0},{0,1},{-1,0},{0,-1}};
void bfs(int x, int y, int block)
{
	queue<P> que;
	que.push(mp(x, y));
	bl[x][y] = block;
	vis[x][y] = true;
	while (!que.empty())
	{
		auto now = que.front();
		que.pop();
		for (int i = 0; i < 4; i ++)
			{
				int newx = now.first + d[i][0];
				int newy = now.second + d[i][1];
				if (newx >= 1 && newx <= n && newy >= 1 && newy <= n
				&& !vis[newx][newy] && arr[newx][newy] != arr[now.first][now.second])
				{
					bl[newx][newy] = block;
					vis[newx][newy] = true;
					que.push(mp(newx, newy));
				}
			}
	}
}
int main()
{
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
		{
			char ch;
			scanf(" %c", &ch);
			arr[i][j] = ch - '0';
		}
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
			if (!bl[i][j])
			{
				bfs(i, j, ++l);
				siz[l]++;
			}
			else
				siz[bl[i][j]]++;
	while (m--)
	{
		int x, y;
		cin >> x >> y;
		cout << siz[bl[x][y]] << endl;
	}
	return 0;
}
2021/7/20 12:25
加载中...