CF1345D-Monopole Magnets (dfs求联通块个数)
题意:
给你一幅图,‘#’代表黑格,‘.’代表白格,让你在满足以下条件的情况下计算出最少的需要摆放的指北针数,若无解则输出-1
1:每行每列必须至少有一枚指南针
2:指北针能到达所有的黑格
3:指北针到不了所有的白格
如果指北针所在的行和列存在指南针,指北针可以向指南针的方向移动
题目链接:https://codeforces.com/contest/1345/problem/D
思路:
首先我们考虑无解的情况,通过观察我们可以发现如果每行或每列中的任意两个黑格之间存在白格,那么是无解的,
原因如下:
若两个黑格所在的块中都有一枚指南针,那么当指北针在其中一块时,肯定会被另一块的
指南针所吸引,从而到达白格,违背了条件3
若黑格中全都摆放指北针,如果不违背条件1,那么必须在白格摆放指南针,那么指北针还是能到达白格,违背条件3
若在一个黑块中全都摆放指北针,另一个黑块中摆放指南针,同样会违背条件3
第二种无解的情况:
有全为白格的行(列)但无全为白格的列(行)
这种情况下在白格处放指南针也会使指北针到达白格
判断好这两种情况后,只需要dfs求联通块个数即可。
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int MAXN=2e5+5; const int INF =1e9; string s[2000]; int ans=0,n,m; int dir[4][2]= {0,1,0,-1,1,0,-1,0}; int visit[1005][1005]; void dfs(int x,int y) { if(x<0||x>=n||y<0||y>=m) return; if(visit[x][y]) return; if(s[x][y]=='.') return; visit[x][y]=1; for(int i=0; i<4; i++) { int nx=x+dir[i][0],ny=y+dir[i][1]; dfs(nx,ny); } } int main() { ios::sync_with_stdio(false); cin.tie(0); cin>>n>>m; for(int i=0; i<n; i++) cin>>s[i]; int flag; for(int i=0; i<n; i++) { flag=0; for(int j=0; j<m; j++) { if(s[i][j]=='.') { if(flag==1) flag=2; } else { if(!flag) flag=1; else if(flag==2) { cout<<"-1"<<endl;return 0; } } } } for(int i=0; i<m; i++) { flag=0; for(int j=0; j<n; j++) { if(s[j][i]=='.') { if(flag==1) flag=2; } else { if(!flag) flag=1; else if(flag==2) { cout<<"-1"<<endl;return 0; } } } } int e_r=0,e_c=0; for(int i=0; i<n; i++) { int j; for(j=0; j<m; j++) { if(s[i][j]!='.') break; } if(j==m) { e_r=1;break; } } for(int i=0; i<m; i++) { int j; for(j=0; j<n; j++) { if(s[j][i]!='.') break; } if(j==n) { e_c=1;break; } } if((e_c&&!e_r)||(e_r&&!e_c)) { cout<<"-1"<<endl;return 0; } for(int i=0; i<n; i++) { for(int j=0; j<m; j++) { if(s[i][j]=='#'&&!visit[i][j]) { dfs(i,j);ans++; } } } cout<<ans<<endl; return 0; }