定义:
并查集是一种树型的数据结构,用于处理一些不相交集合的合并及查询问题(即所谓的并、查)。比如说,我们可以用并查集来判断一个森林中有几棵树、某个节点是否属于某棵树等。
主要构成:
还有初始化
并查集主要由一个整型数组pre[ ]和两个函数find( )、join( )构成。
数组 pre[ ] 记录了每个点的前驱节点是谁,函数 find(x) 用于查找指定节点 x 属于哪个集合,函数 join(x,y) 用于合并两个节点 x 和 y 。
作用:
并查集的主要作用是求连通分支数(如果一个图中所有点都存在可达关系(直接或间接相连),则此图的连通分支数为1;如果此图有两大子图各自全部可达,则此图的连通分支数为2……)
原文链接:https://blog.csdn.net/the_ZED/article/details/105126583
代码模板:
int find(int x) //查找x
{
while(pre[x] != x)
x = pre[x];
return x;
}
void join(int x,int y)
{
int fx=find(x), fy=find(y);
if(fx != fy)
pre[fx]=fy;
}
//路径压缩
int find(int x) //查找结点 x的根结点
{
if(pre[x] == x) return x; //递归出口:x的上级为 x本身,即 x为根结点
return pre[x] = find(pre[x]); //此代码相当于先找到根结点 rootx,然后pre[x]=rootx
}
相关应用:
用并查集判断是否是一棵树:
1.只有一个根(节点总数-连通线数==1)
2.不能成环(对于一对节点,父子必须来自不同的根,父子的根不能一样)
3.只有一个父节点(儿子的根必须是自己,若儿子的根已经指向一个,再指向父亲,组会出现环)
最小生成树:
1.kruskal算法:
1把图中所有边按代价从小到大排序
2把图中n个顶点看成独立n棵树组成的森林
3按排好的权值从小到大选择边,所选的边连接两个顶点,应属于两颗不同的树,(若相同则说明这条边不选也可以,反正有相同的根,)则成为最小生成树的一条边,并将这两颗树合并成一棵树。
4重复3,直到所有顶点都在一棵树内或者有n-1条边为止
从边的权值从小到大开始便利,如果这条边的两个端点不属于一个集合就把他们合并,直到所有点都属于一个集合为止
代码:
for(int i=0;i<n;i++){
if(find(a[i].a)!=find(a[i].b)){
unite(a[i].a,a[i].b);
res+=a[i].value;
}
}
2.Prim算法