cf_936D
这道题,属实将我搞懵了,看了好久才将题意看懂。
刚开始因为认为除了特判情况下,每一行每一列都要存在#,然后当#之间存在’ . ‘时便直接为-1.
后来发现存在情况,当行和列都存在空行时也符合条件。
最基本例子:

当第一行和最后一列都为.,反而能在(1,n)处放N极,且不影响,因此只要将这个条件判过,这道题就能过了。
#include<iostream>
#include<string>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
const int N=2e5;
int mp[1005][1005];
vector<int> rs[1005],cc[1005];
int r[1005],c[1005];
int vis[1005][1005];
struct node{
int x,y;
};
int n,m;
int bfs(int x,int y){
node s;
int dir[4][2]={{1,0},{-1,0},{0,1},{0,-1}};
s.x=x,s.y=y;
vis[x][y]=1;
queue<node> sk;
sk.push(s);
while(!sk.empty()){
node k=sk.front();
sk.pop();
int nx=k.x,ny=k.y;
for(int i=0;i<4;i++){
int dx=nx+dir[i][0];
int dy=ny+dir[i][1];
if(!vis[dx][dy]&&mp[dx][dy]==0&&(dx>=1&&dx<=n&&dy>=1&&dy<=m)){
vis[dx][dy]=1;
sk.push(node{dx,dy});
}
}
}
return 1;
}
int main(){
cin>>n>>m;
int op=0;
int sum=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
char a;cin>>a;
if(a=='.'){
mp[i][j]=1;
vis[i][j]=1;
}
else{
op++;
rs[i].push_back(j);
cc[j].push_back(i);
r[i]++;
c[j]++;
}
}
}
if(op==0){
cout<<0<<endl;
return 0;
}
int fx=0,fy=0;
for(int i=1;i<=n;i++){//判断空行
if(r[i]==0){
fx=1;
}
}
for(int j=1;j<=m;j++){//空列
if(c[j]==0){
fy=1;
}
}
if(fx^fy){//当都存在空行或都不存在时可继续,反正输出-1
cout<<-1<<endl;
return 0;
}
for(int i=1;i<=n;i++){//判断#之间是否存在‘。’
if(rs[i].size()>=2){
for(int j=1;j<rs[i].size();j++){
int s=rs[i][j]-rs[i][j-1];
if(s!=1){
cout<<-1<<endl;
return 0;
}
}
}
}
for(int i=1;i<=m;i++){//同上
if(cc[i].size()>=2){
for(int j=1;j<cc[i].size();j++){
int s=cc[i][j]-cc[i][j-1];
if(s!=1){
cout<<-1<<endl;
return 0;
}
}
}
}
for(int i=1;i<=n;i++){//计算连通块数量。
for(int j=1;j<=m;j++){
if(!vis[i][j]){
sum+=bfs(i,j);
}
}
}
cout<<sum<<endl;
return 0;
}

浙公网安备 33010602011771号