洛谷P1141 01迷宫
抄的题解,主要在于联想到把通路看成连通块,每个点的答案就是所在连通块的大小
用到技巧:二维坐标变为一维的映射
#include<iostream> #include<string> #include<cmath> #include<cstring> #include<vector> #include<map> #include<set> #include<algorithm> #include<queue> #include<stack> #include<list> #include<sstream> #include<cstdio> #define INF 0x3f3f3f3f //const int maxn = 1e6 + 5; const double PI = acos(-1.0); typedef long long ll; using namespace std; const int maxn = 1010; int n, m; char mp[maxn][maxn]; int pre[maxn * maxn]; int num[maxn * maxn]; //统计连通块的大小 int Find(int x) { return pre[x] != x ? pre[x] = Find(pre[x]) : x; } void Union(int x, int y) { int p = Find(x), q = Find(y); if (p != q) pre[q] = p; } inline int f(int y, int x) { //二维并查集不好处理,降维映射 return y * n + x; } int main() { scanf("%d%d", &n, &m); for (int i = 0; i < n; i++) { scanf("%s", mp[i]); for (int j = 0; j < n; j++) { num[f(i, j)] = 0; pre[f(i, j)] = f(i, j); if (i > 0) if (mp[i][j] != mp[i - 1][j]) Union(f(i, j), f(i - 1, j)); if (j > 0) if (mp[i][j] != mp[i][j - 1]) Union(f(i, j), f(i, j - 1)); } } for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { num[Find(f(i, j))]++; } } while (m--) { int x, y; scanf("%d%d",&y,&x); printf("%d\n", num[Find(f(y - 1, x - 1))]); } return 0; }