洛谷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;
}
View Code
原文地址:https://www.cnblogs.com/hznumqf/p/12313339.html