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

  

猜你喜欢

转载自www.cnblogs.com/Ean1zhi/p/12953521.html
今日推荐