并查集

路径压缩并查集

#include<cstdio>

class UnionSet {
 private:
  int *father;
 public:
  UnionSet() : father(NULL) {  }
  UnionSet(int len) : father(NULL) {
    init(len);
  }
  void init(int len) {
    delete[] father;
    father = new int[len + 1];
    for(int i = 0; i <= len; ++i) {
      father[i] = i;
    }
  }
  int find(int son) {
    return son == father[son] ? son : father[son] = find(father[son]);
  }
  void join(int a, int b) {
    father[find(a)] = find(b);
  }
};

按秩合并并查集

#include<cstdio>

class UnionSet {
 private:
  int *father;
  int *depth;
 public:
  UnionSet() : father(NULL) {  }
  UnionSet(int len) : father(NULL) {
    init(len);
  }
  void init(int len) {
    delete[] father;
    father = new int[len + 1];
    delete[] depth;
    depth = new int[len + 1];
    for(int i = 0; i <= len; ++i) {
      father[i] = i;
      depth[i] = 0;
    }
  }
  int find(int son) {
    while(father[son] != son) son = father[son];
    return son;
  }
  void join(int a, int b) {
    a = find(a);
    b = find(b);
    if(depth[a] > depth[b]) std::swap(a, b);
    father[a] = b;
    if(depth[a] == depth[b]) ++depth[b];
    return;
  }
};

回滚并查集

#include<cstdio>
#include<stack>

class UnionSet {
 private:
  int *father;
  int *depth;
  std::stack<std::pair<int, int> > fatherc;
  std::stack<std::pair<int, int> > depthc;
 public:
  UnionSet() : father(NULL) {  }
  UnionSet(int len) : father(NULL) {
    init(len);
  }
  void init(int len) {
    delete[] father;
    father = new int[len + 1];
    delete[] depth;
    depth = new int[len + 1];
    while(!fatherc.empty()) fatherc.pop();
    while(!depthc.empty()) depthc.pop();
    for(int i = 0; i <= len; ++i) {
      father[i] = i;
      depth[i] = 0;
    }
  }
  int find(int son) {
    while(father[son] != son) son = father[son];
    return son;
  }
  void join(int a, int b) {
    a = find(a);
    b = find(b);
    if(depth[a] > depth[b]) std::swap(a, b);
    fatherc.push(std::make_pair(a, father[a]));
    father[a] = b;
    depthc.push(std::make_pair(b, depth[b]));//为了写起来方便,即使depth没被修改也记录一下 
    if(depth[a] == depth[b]) ++depth[b];
    return;
  }
  void undo() {
    father[fatherc.top().first] = fatherc.top().second;
    fatherc.pop();
    depth[depthc.top().first] = depthc.top().second;
    depthc.pop();
  }
};

可持久化并查集

//TODO