- 张乔淞 的博客
染色法求连通块
- 2024-11-30 11:32:36 @
染色法求连通块个数就是for循环遍历整个地图,如果地图的第(i,j)个点没有障碍并且也没被其他颜色给染过那就从这里开始染,并把从这个点能到达的所有点都染成对应的颜色,每执行一次开始染色操作就cnt++,最终cnt就是该地图所有的连通块个数
-
辅助思考1:注意,这里的染色其实就是用数组标记该点,并把每一个连通块的颜色都染成不同的(比如说说连通块1在数组里每个坐标值即存的是1,连通块2在数组里每个坐标值存的是2,连通块3在数组里每个坐标值存的是3 ...... 以此类推),这样就可以很方便的查询地图上的点(sx,sy)和点(fx,fy)是不是同一个连通块了。
-
辅助思考2: 我们可以用idx来存我们当前是在第几个连通块,初始是1,如果符合上述可染色条件那就开始染色,每搜索到一个点就把染色数组的这个点的坐标值设为idx,结束该连通块的染色后把idx++即可
示例代码:
/*其余非注释部分请自请思考*/
#include <bits/stdc++.h>
using namespace std;
int a[30][30]; // 染色数组
bool vis[30][30], st[30][30];
int idx = 1;
int n, m;
int cnt; // 连通块个数
int dx[] = {1, -1, 0, 0}, dy[] = {0, 0, 1, -1};
void dfs(int x, int y)
{
a[x][y] = idx; // 染色
for (int i = 0; i < 4; i++)
{
int nx = x + dx[i];
int ny = y + dy[i];
if (nx >= 1 && nx <= n && ny >= 1 && ny <= m && st[nx][ny] == 0 && vis[nx][ny] == 0)
{
st[nx][ny] = 1;
dfs(nx, ny);
}
}
}
int main()
{
cin >> n >> m; // 地图大小
int q; // 障碍个数
cin >> q;
while (q--)
{
int x, y;
cin >> x >> y; // 障碍的下标
vis[x][y] = 1; // 标记
}
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
if (a[i][j] == 0 && vis[i][j] == 0)
{
st[i][j] = 1;
cnt++;
dfs(i, j);
memset(st, 0, sizeof st);
idx++; // 切换颜色(因为要下一个连通块了)
}
}
}
puts("连通块个数:");
printf("%d\n", cnt);
puts("染色情况:");
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= m; j++)
{
cout << a[i][j] << ' ';
}
puts("");
}
return 0;
}