视频刷题笔记 并查集以及例题

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
数组下标表示城市编号,数组的数值表示能到达这个城市的城市编号。如果下标和数值相等,则为集合的祖先。

查找某个元素所在集合:
也就是查找某个元素所在集合的祖先

int find(int x){
		if(tree[x]==x)
		  return x;
		return tree[x]=find(tree[x]);//如果没找到则继续向上查找祖先 
	}

集合的并运算:
分别找x1 x2两个元素所在集合的祖先,如果不是一个祖先,则将其中一个祖先设置成另一个集合祖先的值

void megre(int x,int y){
		int fx=find(x);
		int fy=find(y);
		if(fx!=fy)
		tree[fx]=fy;//把fy设置成了fx的祖先 
	}

在这里插入图片描述
思路:n个城市至少需要n-1条道路联通。将给定的城市看成大集合,相连的道路合并成小集合,小集合个数(祖先数)看成大城市的个数,那么最后的结果就是小集合数减1

#include<iostream>
#include<cstdio>
using namespace std;
void initial(int *a,int n){
	for(int i=1;i<=n;i++)
	   a[i]=i;
} 
int find(int s[],int x){
	/*如果不是祖先,则将x的祖先赋值给x,
		意思就是,x一直向上找祖先*/ 
	while(s[x]!=x)
	    x=s[x];		
	 return x; //此时,下标和值相等,找到祖先 
} 
void union1(int s[],int x,int y){
	int fx=find(s,x);
	int fy=find(s,y);
	if(fx!=fy)
	s[fx]=fy;
}
//确定最后划分的集合的个数,也就是分类后集合的个数 
int find_ans(int s[],int n){
	int sum=0;
	for(int i=1;i<=n;i++){
		if(s[i]==i)
		 ++sum;
	return sum;
	}
} 

int main(){
	int m=0,n=0;
	while(1){
		cout<<"输入城镇的数目和道路数目:"<<endl; 
		cin>>n>>m;
		if(n==0)
		break;
		//建立动态数组 
	  int *arr=new int[n+1];
	//初始化,也就是将祖先都看成自己 
	  initial(arr,n);
	//集合合并,也就是把数字归类到祖先下
	  int a=0,b=0; 
		 for(int i=0;i<m;i++){
		 	cin>>a>>b;
		 	union1(arr,a,b);
		 }
		cout<<find_ans(arr,n)-1<<endl;
	
	}

	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值