并查集
一、作用
二、概述
1.基本思想
在遍历图的每一条边时,若存在集合包含其连接的任意顶点,则将另一顶点放到该集合中,否则将这两顶点放入新集合中。若边的两个顶点分别位于两个集合内,则将两个集合合并。注意:任意集合中两点是互通的,每个集合对应一个连同分量。
2.代码
用每个集合的祖先代表对应的集合,定义数组parent[n]代表每个顶点位于哪个集合
int[] parent = new int[pnum+1];
for(int i = 1;i <= pnum;i++)
{
//初始时祖先为其自身
parent[i] = i;
}
查找顶点p所在集合
//找祖先
public int find(int[] parent,int p)
{
//若祖先不为自身,代表存在祖先,递归查找祖先的祖先
if(parent[p] != p)
parent[p] = find(parent,parent[p]);
//返回p祖先
return parent[p];
}
合并为同一集合
public void union(int[] parent,int p1,int p2)
{
//让p2的祖先成为p1祖先的祖先
parent[find(parent,p1)] = find(parent,p2);
}
遍历,构造并查集
for(int i = 0;i < edges.length;i++)
{
int p1 = edges[i][0],p2 = edges[i][1];
//若两点位于不同集合
//若findzuxian(parent,p1) == p1 && findzuxian(parent,p2) == p2 将两点放入新集合中
if(find(parent,p1) != find(parent,p2))
{
//合并集合
union(parent,p1,p2);
}
else
//该边两个顶点位于同一集合,构成回路 ①
}**
计算连同分量
for (int i = 0; i < provinces; i++)
{
if (parent[i] == i) //计算祖先(根节点)个数
{
circles++;
}
}