岛屿数量+并查集

  小伙伴们大家好,今天给大家带来并查集的使用。先给大家看一道题:

问题分析

  举个例子:

 

  此矩阵共有3个岛屿(只有上下左右直接相连才是同一片岛屿,斜着连接并不是)

  我们可以使用感染的方法: 

  设想我们遍历整个矩阵,当遇见1时将和其本身和与其属于同一片岛屿的矩阵其它元素的值替换为2,同时岛的数量加一。第一次遇见1后,矩阵如图所示:

  继续遍历矩阵,重复上述过程,遇见第0行第4列的1,继续感染,同时岛的数量加一:

 

  此时岛的数量为2 ,继续遍历,直到遇见最后一个1,岛的数量加一变为3。

代码展示

#include<iostream>
using namespace std;
int arr[4][6];
void infect(int i,int j,int n,int m){
	if(i<0||i>=n||j<0||j>=m||arr[i][j]!=1){
		return;
	}
	arr[i][j]=2;
	infect(i-1,j,n,m);
	infect(i+1,j,n,m);
	infect(i,j-1,n,m);
	infect(i,j+1,n,m);
}
int main(){
	int count=0;
	for(int i=0;i<4;i++){
		for(int j=0;j<6;j++){
			cin>>arr[i][j];
		}
	}
	for(int i=0;i<4;i++){
		for(int j=0;j<6;j++){
			if(arr[i][j]==1){
				count++;
				infect(i,j,4,6);
			}
		}
	}
	cout<<"岛的数量为:"<<count;
} 

  数组大小大家自行确定。

进阶要求

  如果我们给原问题添加要求:使用并行算法。即由多个cpu,那么我们就可以实现每个cpu完成一块区域。假设由两个cpu,我们将原区域平均分为两块,分别计算。每个cpu都会计算出该区域岛屿数量,最后再添加合并逻辑即可。(因为可能重复计数,原先属于同一块岛屿被边界切开了)这也就要求我们除了每个区域除了计算数量还要记录边界,最后利用边界重新计算岛屿。那如何利用边界呢?那就是合并集。

并查集相关代码

void create(int head[],int level[],int n){
	for(int i=0;i<n;i++){
		head[i]=i;
		level[i]=1;
	}
}
int find(int x,int head[]){
	if(x==head[x])
	    return x;
	return head[x]=find(head[x],head);//路径压缩以后找head[i]为O(1) 
}
void merge(int level[],int head[],int x,int y){
	x=find(x,head);
	y=find(y,head);
	if(x==y)
	    return;
	if(level[x]<=level[y]){
		head[x]=y;//小高度向大高度合并 
	}
	else{
		head[y]=x;
	}
	if(level[x]==level[y])//更新高度(相等时大高度加一其它情况不变) 
	    level[y]++;
}

  create函数:初始化并查集,每个元素的根为自己本身。并且每个元素所属部分高度为1。(只有自己一个元素)

  find函数:找到某个元素的根,并且注意最后路径压缩。

  merge函数:集合合并,首先判断两个元素的根是否相同,如果相同无需合并,不同则合并。并且高度低的集合向高度高的集合合并。(减小合并后集合的高度) 

  回到这道题目,如何利用边界重新计算数量呢?那就是记录边界为1的元素位置,如果左右区域相连则查看是否属于同一集合,若是不用管,不是岛屿原数量减一,并将两个集合合并。

  代码实现较难,大家不太需要实现,只需明白思路即可,思路同样适用于更多的cpu,无疑边界多了就是。

  感谢观看,大家多多点赞支持!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

玛卡巴卡(努力学习版)

谢谢支持新手小白每天持续更新

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值