染色法求连通块个数就是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;
}

终于写完了累死我了