1 条题解
-
0
Guest
-
3
考查连通块的个数,我们有两种方法解决:
- 搜索
- 并查集
奈何本人并查集学魔怔了,所以这一道题着重讲解并查集。
并查集
思路分析
对于一个 的矩阵 ,如果 是
.
,则和左边以及上边的合并(如果可能的话)(请读者自行思考为何只要合并两个方向)。 合并完后,查询有多少个集合即可。代码实现
#include<bits/stdc++.h> using namespace std; int fa[400005],n,m; char martix[205][205]; int find(int x){//并查集模版:查询、合并 return x==fa[x]?x:fa[x]=find(fa[x]); } void merge(int x,int y){ fa[find(x)]=find(y); } int change(int i,int j){//把二维的转成一维的 return i*m+j; } void init(int x){//并查集初始化 for(int i=0;i<x;i++){ fa[i]=i; } } int main(){ freopen("water.in","r",stdin); freopen("water.out","w",stdout); cin>>n>>m; init(n*m); for(int i=0;i<n;i++){//输入 for(int j=0;j<m;j++){ cin>>martix[i][j]; } } for(int i=0;i<n;i++){ for(int j=0;j<m;j++){ if(martix[i][j]=='#') continue;//如果是陆地,pass if(i>0){//如果不在左边界 if(martix[i-1][j]=='.')//(防RE),且左边有水 merge(change(i,j),change(i-1,j));//合并 } if(j>0){//如果不在上边界 if(martix[i][j-1]=='.') //且上边有水 merge(change(i,j),change(i,j-1));//合并 } } } int cnt=0; for(int i=0;i<n;i++){//统计 for(int j=0;j<m;j++){ if(martix[i][j]=='#') continue; if(fa[change(i,j)]==change(i,j)) cnt++; //如果fa[i]==i,说明是一个集合,统计 } } cout<<cnt; return 0; }
搜索
思路
- 定义 记录访问,函数(函数名自拟),参数为矩阵、、。
- 如果越界或不是水或已访问,退出。
- 将 设置成 。
- 四个方向查找。
代码
思路这么详细了,相信各位不需要。总结
难度:黄(普及 ~ 提高-)。
最后,看到这了,点个赞吧,写代码不容易!
- 1
信息
- ID
- 775
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 9
- 标签
- (无)
- 递交数
- 37
- 已通过
- 2
- 上传者