搬运我的洛谷题解,原文创作时间:2026-05-11 18:42。
思路:
这道题可以用广度优先搜索写。
对于每个没访问的块使用广度优先搜索,找连通块。
搜索时套广度优先搜索的公式即可。
在搜索过程中,记录连通块的边界:最小行号 $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;
}