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; }