1000ms
- 131072K
在一个 n×mn \times mn×m 的方格地图上,某些方格上放置着炸弹。手动引爆一个炸弹以后,炸弹会把炸弹所在的行和列上的所有炸弹引爆,被引爆的炸弹又能引爆其他炸弹,这样连锁下去。
现在为了引爆地图上的所有炸弹,需要手动引爆其中一些炸弹,为了把危险程度降到最低,请算出最少手动引爆多少个炸弹可以把地图上的所有炸弹引爆。
输入格式
第一行输两个整数 n,mn,mn,m,用空格隔开。
接下来 nnn 行,每行输入一个长度为 mmm 的字符串,表示地图信息。
0
表示没有炸弹,1
表示炸弹。数据约定:
对于 60%60\%60% 的数据:1≤n,m≤1001 \le n, m \le 1001≤n,m≤100;
对于 100%100\%100% 的数据:1≤n,m≤1000 1 \le n, m \le 10001≤n,m≤1000;
数据量比较大,不建议用
cin
输入。输出格式
输出一个整数,表示最少需要手动引爆的炸弹数。
样例输入
5 5 00010 00010 01001 10001 01000
样例输出
2
样例的方法如下:先引手动引爆一个炸弹,红色的手动引爆,绿色的是间接引爆。
然后再手动引爆一个炸弹:
因此最少需要手动引爆两枚炸弹。
思路:并查集
#include<iostream> #include<string> #include<algorithm> #include<vector> #include<set> #include<cstdio> #include<cstring> #include<cmath> using namespace std; const int maxn=1005; struct edge { int from,to; }Edge[maxn*maxn]; int pre[maxn]; bool cmp(const edge &a, const edge &b) { if(a.from==b.from) return a.to<b.to; return a.from<b.from; } int findfather(int x) { if(pre[x]!=x) pre[x]=findfather(pre[x]); return pre[x]; } void change(int son, int f) { if(pre[son]!=f) { change(pre[son],f); pre[son]=f; } } int main() { int n,m; scanf("%d %d\n",&n,&m); char s[m+1]; int index=0; for(int i=0;i<n;++i) { gets(s); for(int j=0;j<m;++j) { if(s[j]=='1') { Edge[index].from=i; Edge[index].to=j+n; index++; } } } for(int i=0;i<maxn;++i) pre[i]=i; sort(Edge,Edge+index,cmp); for(int i=0;i<index;++i) { int f1=findfather(Edge[i].from),f2=findfather(Edge[i].to); if(f1!=f2) { pre[f1]=f2; } } set<int> ans; for(int i=0;i<index;++i) { ans.insert(findfather(Edge[i].from)); ans.insert(findfather(Edge[i].to)); } int result=ans.size(); printf("%d\n",result); return 0; }