https://codeforces.com/contest/1344/problem/B
分情况讨论
1.如果一行没有黑色,那么说明这一行是不能到达的,但是又必须放一个S,那么必须要有一列也全是白色,才能放下这个S
2.如果一行有黑色,那么这一串黑色必须要连在一起,不然,由于这一行必须放一个S,放左边放右边,那么某个N到另一边的黑色部分的时候,都能越过一些白色到达另一边,与定义矛盾。
如果可行,那么黑色联通块的数量就是答案,这个手玩一下就行了。
//代码里的inrowincol没撒用,当时写复杂了。
#include
using namespace std;
typedef long long ll;
const int maxl=1010;
int n,m,ans,cas,flagrow,flagcol;
int a[maxl][maxl];
char s[maxl][maxl];
struct node
{
int x,y;
};
queue q;
int tx[5]={0,1,0,-1,0};
int ty[5]={0,0,1,0,-1};
bool inrow[maxl],incol[maxl];
inline void prework()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%s",s[i]+1);
for(int i=1;i<=n;i++)
inrow[i]=false;
for(int j=1;j<=m;j++)
incol[j]=false;
flagrow=0;flagcol=0;
ans=0;int l,r;
for(int i=1;i<=n;i++)
{
l=0,r=0;
for(int j=1;j<=m;j++)
if(s[i][j]=='#')
{
l=j;break;
}
for(int j=m;j>=1;j--)
if(s[i][j]=='#')
{
r=j;break;
}
if(l==0)
{
inrow[i]=true;
flagrow=1;
continue;
}
for(int j=l;j<=r;j++)
if(s[i][j]=='.')
{
ans=-1;
return;
}
}
for(int j=1;j<=m;j++)
{
l=0;r=0;
for(int i=1;i<=n;i++)
if(s[i][j]=='#')
{
l=i;break;
}
for(int i=n;i>=1;i--)
if(s[i][j]=='#')
{
r=i;break;
}
if(l==0)
{
incol[j]=true;
flagcol=1;
continue;
}
for(int i=l;i<=r;i++)
if(s[i][j]=='.')
{
ans=-1;return;
}
}
if(flagrow && !flagcol){ans=-1;return;}
if(!flagrow && flagcol){ans=-1;return;}
}
inline void bfs(int sx,int sy)
{
while(!q.empty()) q.pop();
int x,y,xx,yy;node d;
d=node{sx,sy};a[sx][sy]='.';q.push(d);
while(!q.empty())
{
d=q.front();q.pop();
x=d.x;y=d.y;
for(int i=1;i<=4;i++)
{
xx=x+tx[i];yy=y+ty[i];
if(xx<1 || xx>n || yy<1 || yy>m)
continue;
if(s[xx][yy]=='#')
{
s[xx][yy]='.';d=node{xx,yy};
q.push(d);
}
}
}
ans++;
}
inline void mainwork()
{
if(ans<0)
return;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(s[i][j]=='#')
bfs(i,j);
}
inline void print()
{
if(ans<0)
puts("-1");
else
printf("%d\n",ans);
}
int main()
{
int t=1;
//scanf("%d",&t);
for(cas=1;cas<=t;cas++)
{
prework();
mainwork();
print();
}
return 0;
}