算法学习笔记之并查集

并查集

基础

定义

并查集是一种维护集合的数据结构,“并”、“查”、“集”分别取自Union(合并)、Find(查找)、Set(集合)三个单词。

  • 实现:数组
int father[N];

如果father[i]==i就代表该点是根节点,每一个集合只有一个根节点,并且将其作为所属集合的标志
算法学习笔记之并查集_第1张图片

//上图使用并查集存储如下
father[1]=1;
father[2]=1;
father[3]=2;
father[4]=2;
father[5]=5;
father[6]=5;

算法学习笔记之并查集_第2张图片

基本操作
  • 初始化
for(int i=1;i<=N;i++){
	father[i]=i;
}
  • 查找
//递推写法
int findFather(int x){
	while(father[x]!=x){
		x=father[x];
	}
return i;
}
//递归写法
int findFather(int x){
	if(x==father[x])return x;
	return findFather(father[x]);
}
  • 合并
    将两个集合合并到一起,先找到各自集合的根节点,然后将一个集合的根节点指向另一个集合的根节点,代码省略

应用实例----七段码(蓝桥杯真题)

算法学习笔记之并查集_第3张图片

#define N 10
int f[N];
bool st[N];//记录路径
int en[N][N];//表示两条边是否相连
int ans=0;

int find(int x){
	if(x==f[x])return x;
	else return find(f[x]);
}

void init(){
	for(int i=1;i<=N;i++){
		f[i]=i;
		st[i]=false;
	}	
}

void dfs(int x){
	if(x>7){
		init();
		for(int i=1;i<=N;i++)
			for(int j=1;j<=N;j++){
				if(en[i][j]&&st[i]&&st[j])
					f[find(x)]=find[j];
		int cnt=0;
		//只有一个集合说明选中的每条边都相邻
		for(int i=1;i<=N;i++){
			if(st[i]&&f[i]==i)
				cnt++;
		if(cnt==1)ans++;
		return;
	}
	st[x]=true;
	dfs(x+1);
	st[x]=false;
	dfs(x+1);
}

int main(){
	//记录各边相连情况
	en[1][2]=1;en[1][6]=1;
	en[2][1]=1;en[2][3]=1;en[2][7]=1;
	en[3][2]=1;en[3][4]=1;en[3][7]=1;
	en[4][3]=1;en[4][5]=1;
	en[5][4]=1;en[5][6]=1;en[5][7]=1;
	en[6][1]=en[6][5]=en[6][7]=1;
	en[7][2]=en[7][3]=en[7][5]=en[7][6]=1;
	
	dfs(1);//从a开始深度优先遍历,每遍历一次就得到一种亮灯方案

	cout<<ans>>endl;
	return 0;
}

你可能感兴趣的:(算法,c++,算法)