1.并查集模板
1.普通路径压缩
private class UnionFind{
private int[] parent;
public UnionFind(int n) {
parent = new int[n];
for (int i=0;i<n;i++) {
parent[i]=i;
}
}
/**
* 路径压缩
*/
public int find(int x) {
if(x!=parent[x]) {
parent[x] = find(parent[x]);
}
return parent[x];
}
public void union(int x,int y) {
int rootX = find(x);
int rootY = find(y);
if(rootX == rootY) {
return;
}
parent[rootX] = rootY;
}
public boolean isConnected(int x, int y) {
return find(x) == find(y);
}
}
2.需要获得并查集的大小时
加入一个size[]数组储存根节点连接的节点的数量。
调用getsize函数返回以该节点为根节点的子树的节点的数量。
private class UnionFind {
/**
* 当前结点的父亲结点
*/
private int[] parent;
/**
* 以当前结点为根结点的子树的结点总数
*/
private int[] size;
public UnionFind(int n) {
parent = new int[n];
size = new int[n];
for (int i = 0; i < n; i++) {
parent[i] = i;
size[i] = 1;
}
}
public int find(int x) {
if (x != parent[x]) {
parent[x] = find(parent[x]);
}
return parent[x];
}
public void union(int x, int y) {
int rootX = find(x);
int rootY = find(y);
if (rootX == rootY) {
return;
}
parent[rootX] = rootY;
// 在合并的时候维护数组 size
size[rootY] += size[rootX];
}
/**
* @param x
* @return x 在并查集的根结点的子树包含的结点总数
*/
public int getSize(int x) {
int root = find(x);
return size[root];
}
}
3.需要获得连通分量
可以在构造函数中传入一共需要合并的点的所有个数,然后在union函数中,毎合并两点减去一个count,剩下的就是根节点的个数。
public static class UnionFind {
private int parent[];
private int count;
public UnionFind(int n,int count) {
this.parent = new int[n];
this.count = count;
for(int i=0;i<n;i++) {
parent[i]=i;
}
}
public int find(int x,int c) {
if(x!=parent[x]) {
parent[x] = find(parent[x],c++);
}
return parent[x];
}
public void union(int x,int y) {
int rootX = find(x,0);
int rootY = find(y,0);
if(rootX == rootY) {
return;
}
parent[rootX] = rootY;
count--;
}
public int getCount() {
return this.count;
}
}