并查集,查两点是否连通
参考:https://www.cs.princeton.edu/courses/archive/spring13/cos423/lectures/UnionFind.pdf
并查集只有两个操作,查(find)和并(unite)
int find(int x) {
if (parent[x] != x)
parent[x] = find(parent[x]); // 路径压缩
return parent[x];
}
void unite(int x, int y) {
int px = find(x), py = find(y);
if (px == py) return;
parent[px] = py;
}
合并时可以优化。用size[]记录集合大小,初始全为1,合并时以size较大集合作为父集合。
void unite(int x, int y) {
int px = find(x), py = find(y);
if (px == py) return;
if (size[px] < size[py]) swap(px, py);
size[px] += size[py];
parent[py] = px;
}
或者用rank[]记录集合的高,初始全为0,合并时以rank较大集合作为父集合。之所以叫rank[]不叫height[],因为确切来说rank[]并不是高度,“路径压缩”后height[x]<=rank[x]。
void unite(int x, int y) {
int px = find(x), py = find(y);
if (px == py) return;
if (rank[px] < rank[py]) swap(px, py);
if (rank[px] == rank[py]) rank[px]++;
parent[py] = px;
}
也有用str作key,用unordered_map<string, string>作parent的。
初始赋值可以写在find()中
string find(const string &s, unordered_map<string, string> &parent) {
if (!parent.count(s)) parent[s] = s;
if (parent[s] != s)
parent[s] = find(parent[s], parent);
return parent[s];
}