2025 : 简单环路(并查集)

404

题目描述

有一个N x M 大小的地图,地图中的每个单元包含一个大写字母。
若两个相邻的(这里的相邻指“上下左右”相邻)点上的字母相同,我们可以用线段连接这两个点。
若存在一个包含同一字母的环路,那么连接这些点我们可以得到一个多边形,
当且仅当多边形的边数大于等于4时,我们称这幅地图中存在“简单环路”。
现在给你一份地图,你来判断是否存在“简单环路”。
列如:
3 4
AAAA
ABCA
AAAA
字符“A”可以构成一个“简单环路”,其边数为4。

输入

第一行输入两个正整数n,m,2<=n,m<=50,分别表示地图的行列数。
接下来输入n行,每行m个大写字母。

输出

若存在“简单环路”输出“Yes”,否则输出“No”。

样例输入

3 4
AAAA
ABCA
AADA

样例输出

No

思路

并查集,把每个相同的点合成一个祖先。如果遇到两个点相同,而且他们的祖先也相同,那么就形成环了。

AC

#include<bits/stdc++.h>
#define ll long long
#define mem(a, b) memset(a, b, sizeof(a)) 
#define N 105
using namespace std;
char g[N][N];
int n, m;
int pre[N * N];
// 获取每个坐标的唯一id 
int id(int i, int j) {
    return i * m + j; 
}
//祖先初始化 
void init() {
    for (int i = 0; i < N * N; i++) {
        pre[i] = i;
    }
}
// 查找祖先 
int find (int x) {
    if (x == pre[x])    return x;
    else return pre[x] = find(pre[x]);
}
int main() {
//  freopen("in.txt", "r", stdin);
    while (scanf("%d%d", &n, &m) != EOF) {
        for (int i = 0; i < n; i++) {
            scanf("%s", &g[i]);
        }
        init();
        int flag = 0;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                //左右方向 
                if (g[i][j] == g[i][j + 1]) {
                    int u = id(i, j);
                    int v = id(i, j + 1);
                    int find_u = find(u);
                    int find_v = find(v);
                    if (find_u != find_v) {
                        pre[find_u] = pre[find_v];
                        find(find_u);
                    }else {
                        flag = 1;
                        break;
                    }
                }
                //上下方向 
                if (g[i][j] == g[i + 1][j]) {
                    int u = id(i, j);
                    int v = id(i + 1, j);
                    int find_u = find(u);
                    int find_v = find(v); 
                    if (find_u != find_v) {
                        pre[find_u] = pre[find_v];
                        find(find_u);
                    }else {
                        flag = 1;
                        break;
                    }
                }
            }
            if (flag)   break;
        }
        if (flag)   printf("Yes\n");
        else        printf("No\n");
    }


    return 0;
}

猜你喜欢

转载自blog.csdn.net/henuyh/article/details/80365287
今日推荐