搬运我的洛谷题解,原文创作时间:2026-05-11 18:42。

P16439 [XJTUPC 2026] 鲜艳 / 方格

思路:

这道题可以用广度优先搜索写。

对于每个没访问的块使用广度优先搜索,找连通块。

搜索时套广度优先搜索的公式即可。

在搜索过程中,记录连通块的边界:最小行号 $minx$、最小列号 $miny$、最大行号 $maxx$、最大列号 $maxy$。

同时记录连通块的元素个数 $cnt$。

搜索结束后,计算理论面积:$area = (maxx - minx + 1) \times (maxy - miny + 1)$。

如果理论面积不等于元素个数,那么这个连通块就不是矩形,直接输出 No

如果理论面积等于元素个数,则说明这个连通块是矩形,通过。

如果所有连通块都通过检查,就输出 Yes

代码:

#include <bits/stdc++.h>
using namespace std;
int main(){
    int T;
    cin>>T;
    int fx[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
    while(T--){
        int n,m;
        cin>>n>>m;
        vector<vector<char>>a(n+1,vector<char>(m+1));
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                cin>>a[i][j];
            }
        }
        vector<vector<bool>>vis(n+1,vector<bool>(m+1,false));
        bool flag=true;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=m;j++){
                if(!vis[i][j]&&flag!=false){
                    int k=a[i][j];
                    queue<pair<int,int>>q;
                    vis[i][j]=true;
                    q.push({i,j});
                    int minx=i,maxx=i,miny=j,maxy=j;
                    int cnt=1;
                    while(!q.empty()){
                        pair<int,int>r=q.front();
                        q.pop();
                        int x=r.first,y=r.second;
                        for(int l=0;l<4;l++){
                            int nx=x+fx[l][0];
                            int ny=y+fx[l][1];
                            if(nx>=1&&nx<=n&&ny>=1&&ny<=m&&!vis[nx][ny]&&a[nx][ny]==k){
                                vis[nx][ny]=true;
                                q.push({nx,ny});
                                cnt++;
                                minx=min(minx,nx);
                                maxx=max(maxx,nx);
                                miny=min(miny,ny);
                                maxy=max(maxy,ny);
                            }
                        }
                    }
                    int area=(maxx-minx+1)*(maxy-miny+1);
                    if(area!=cnt){
                        cout<<"No\n";
                        flag=false;
                        break;
                    }
                }
                if(!flag)break;
            }
        }
        if(flag==true){
            cout<<"Yes\n";
        }
    }
	return 0;
}