在一个 n \times mn×m 的方格地图上,某些方格上放置着炸弹。手动引爆一个炸弹以后,炸弹会把炸弹所在的行和列上的所有炸弹引爆,被引爆的炸弹又能引爆其他炸弹,这样连锁下去。
现在为了引爆地图上的所有炸弹,需要手动引爆其中一些炸弹,为了把危险程度降到最低,请算出最少手动引爆多少个炸弹可以把地图上的所有炸弹引爆。
输入格式
第一行输两个整数 n,mn,m,用空格隔开。
接下来 nn 行,每行输入一个长度为 mm 的字符串,表示地图信息。0
表示没有炸弹,1
表示炸弹。
数据约定:
对于 60\%60% 的数据:1 \le n, m \le 1001≤n,m≤100;
对于 100\%100% 的数据:1 \le n, m \le 10001≤n,m≤1000;
数据量比较大,不建议用cin
输入。
输出格式
输出一个整数,表示最少需要手动引爆的炸弹数。
样例输入复制
5 5 00010 00010 01001 10001 01000
样例输出复制
2
并查集处理下,x和y坐标值合在一起
这样是为了计算哪些炸弹属于一个种群,之后计算种群数量
一开始直接贪心,后来发现样例都过不了
#include <cstdio>
#include<iostream>
#include <cstring>
#include <algorithm>
#define MAXN 1010
using namespace std;
int n,m;
bool visited[2*MAXN];
int pre[2*MAXN];
char ch[MAXN][MAXN];
void Init() {
for(int i = 0;i <= n+m+2;i++) pre[i] = i;
}
// 路径压缩
int Find(int x) {
if(pre[x]==x) return x;
else return pre[x]=Find(pre[x]);
}
void Union(int x,int y) {
int xx = Find(x);
int yy = Find(y);
if(xx != yy) {
pre[yy] = xx;
}
}
int main() {
// freopen("input.txt","r",stdin);
scanf("%d%d",&n,&m);
Init();
for(int i = 0;i < n;i++)
scanf("%s",ch[i]);
for(int i = 0;i < n;i++)
for(int j = 0;j < m;j++) {
if(ch[i][j]=='1') {
Union(i,j+n);
// cout<<i<<" "<<j<<" "<<pre[i]<<endl;
}
}
int res = 0;
for(int i = 0;i < n;i++)
for(int j = 0;j < m;j++) {
if(ch[i][j]=='1') {
// cout<<i<<" "<<j<<endl;
int t = Find(i);
// cout<<"==="<<t;
if(!visited[t]) res++,visited[t]=1;
t = Find(j+n);
// cout<<"==="<<t<<endl;;
if(!visited[t]) res++,visited[t]=1;
}
}
printf("%d\n",res);
// int aaa;
// scanf("%d",&aaa);
return 0;
}