并查集
并查集
并查集(Java实现) - GoldArowana - 博客园
TODO:补充概念等知识
模板
class DSU {
/**
* initialSize : 初始化集合个数
* currentSize : 当前集合个数
* nodeFathers : 父节点
* nodeCounts : 集合中节点个数
*/
private int initialSize;
private int currentSize;
private int[] nodeFathers;
private int[] nodeCounts;
public DSU(int initialSize) {
this.initialSize = initialSize;
this.currentSize = initialSize;
nodeFathers = new int[initialSize];
nodeCounts = new int[initialSize];
for (int i = 0; i < initialSize; ++i) {
nodeFathers[i] = i;
nodeCounts[i] = 1;
}
}
public int getInitialSize() {
return initialSize;
}
public int getCurrentSize() {
return currentSize;
}
public int getNodeCount(int id) {
return nodeCounts[find(id)];
}
public int[] getNodeFathers() {
return nodeFathers;
}
public int[] getNodeCounts() {
return nodeCounts;
}
/**
* 判断 id 是否符合要求
*
* @param id id
* @return 是否符合要求
*/
private boolean nonstandardId(int id) {
return id < 0 || id >= initialSize;
}
/**
* 查找元素所属集合根节点编号
*
* @param id 待查找元素
* @return 所属集合的根节点编号
*/
public int find(int id) {
if (nonstandardId(id)) {
return -1;
}
if (nodeFathers[id] == id) {
return id;
}
nodeFathers[id] = find(nodeFathers[id]);
return nodeFathers[id];
}
/**
* 判断两个元素是否属于同一个集合
*
* @param x 元素1
* @param y 元素2
* @return 是否属于同一个集合
*/
public boolean same(int x, int y) {
return find(x) == find(y);
}
/**
* 合并两个集合,并返回是否合并成功
*
* @param x 集合1
* @param y 集合2
* @return 是否合并成功
*/
public boolean merge(int x, int y) {
if (nonstandardId(x) || nonstandardId(y)) {
return false;
}
int fx = find(x), fy = find(y);
if (fx == fy) {
return false;
}
// 如果fx的节点个数小于fy,则将fx合并到fy中,否则将fy合并到fx中
if (nodeCounts[fx] < nodeCounts[fy]) {
nodeFathers[fx] = fy;
nodeCounts[fy] += nodeCounts[fx];
} else {
nodeFathers[fy] = fx;
nodeCounts[fx] += nodeCounts[fy];
}
--currentSize;
return true;
}
}