思路是把一个联通块的所有点放到一个集合中(用并查集实现)同时算出该联通块的气,代码只有43分,求hack数据
#include <iostream>
using namespace std;
int dx[4]={0,1,0,-1};
int dy[4]={1,0,-1,0};
const int N=2e3+5,M=2e3+5;
int t,n,m,Map[N][M];
int f[N*M],c[N*M];
int find(int x) {
if(x==f[x]) return x;
else return f[x]=find(f[x]);
}
bool vis[N*M];
bool check() {
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++) {
f[(i-1)*m+j]=(i-1)*m+j; c[(i-1)*m+j]=0;
vis[(i-1)*m+j]=false;
}
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++) {
if(Map[i][j]==1) {
for(int k=0;k<4;k++) {
int x=i+dx[k],y=j+dy[k];
if(Map[x][y] or x==0 or y==0 or x>n or y>m) continue;
else Map[x][y]=2;
int u=find((x-1)*m+y);
for(int d=0;d<4;d++) {
int p=x+dx[d],q=y+dy[d];
if(p==0 or q==0 or p>n or q>m) continue;
int v=find((p-1)*m+q);
if(Map[p][q]==0) c[u]++;
else if(Map[p][q]==2) {
c[u]+=c[v]-1;
f[v]=u;
}
}
}
}
}
int cnt=0;
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)if(Map[i][j]==2) {
//cout<<i<<' '<<j<<endl;
int node=find((i-1)*m+j);
if(!vis[node]) {
vis[node]=true;
cnt+=(c[node]==0);
}
}
//cout<<cnt<<endl;
return cnt>1;
}
int main() {
cin>>t;
while(t--) {
cin>>n>>m;
for(int i=1;i<=n;i++) Map[i][0]=Map[i][m+1]=1;
for(int j=1;j<=m;j++) Map[0][j]=Map[n+1][j]=1;
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++) {
char ch; cin>>ch;
if(ch=='*') Map[i][j]=1;
else Map[i][j]=0;
}
if(check()) cout<<"YES";
else cout<<"NO";
cout<<endl;
}
return 0;
}